Plantilla CRISP-DM: "Climas de Australia"
Integrantes:
- Alejandro Ferrera
- Nicolas Dávila
- Diego Gieminiani
| Columna | Descripción |
|---|---|
| Fecha | Fecha de la observación |
| Ubicación | Ubicación de la estación meteorológica |
| MinTemp | Temperatura mínima en grados Celsius |
| MaxTemp | Temperatura máxima en grados Celsius |
| Lluvia | Cantidad de lluvia registrada ese día en mm. |
| Evaporación | Evaporación (mm) en 24 horas |
| Sol | Número de horas de sol brillante en el día |
| DirRafaga | Dirección de la ráfaga de viento más fuerte en 24 horas. |
| VelRafaga | Velocidad (km/hr) de la ráfaga de viento más fuerte en 24 horas. |
| Dir9am | Dirección del viento a las 9am |
| Dir3pm | Dirección del viento a las 3pm |
| Vel9am | Velocidad (km/hr) del viento a las 9am |
| Vel3pm | Velocidad (km/hr) del viento a las 3pm |
| Hum9am | Porcentaje de humedad a las 9am |
| Hum3pm | Porcentaje de humedad a las 3pm |
| Pres9am | Presión atmosférica (hpa) a nivel del mar a las 9am |
| Pre3pm | Presión atmosférica (hpa) a nivel del mar a las 3pm |
| Nub9am | Fracción del cielo cubierto por nubes a las 9am. Se mide en "octavos", de manera que un valor 0 indica cielo totalmente despejado y 8, cielo totalmente cubierto. |
| Nub3pm | Fracción del cielo cubierto por nubes a las 3pm. Se mide en "octavos", de manera que un valor 0 indica cielo totalmente despejado y 8, cielo totalmente cubierto. |
| Temp9am | Temperatura en grados Celsius a las 9am |
| Temp3pm | Temperatura en grados Celsius a las 3pm |
| Lluvia Hoy | Variable indicadora que toma el valor 1 si la precipitación es en mm. en las últimas 24 hrs. excede 1 mm. y 0 si no. |
| RISK_MM | La cantidad de lluvia. Una especie de medida del "riesgo". |
| Lluvia Man | Variable indicadora que toma el valor 1 si al día siguiente llovió y 0 si no. |
Fase 1: Business Understanding¶
Contexto del caso¶
Se dispone de un set de datos de observaciones meteorológicas diarias de múltiples ubicaciones en Australia, obtenidas de la Oficina de Meteorología de la Commonwealth de Australia y procesadas para crear este conjunto de datos de muestra, los datos se han procesado para proporcionar una variable objetivo RainTomorrow(si hay lluvia al día siguiente - No / Sí) y una variable de riesgo RISK_MM(cuánta lluvia registrada en milímetros), esta información se ha dejado disponible para que usted la explore y busque información que sea relevante para demostrar su aprendizaje de Minería de datos.
Para poder dar el mejor apoyo en la toma de decisiones de "Climas de Australia" nos encontramos con desafíos como:
- Identificar patrones y relaciones en los datos de las caracteristicas del clima para entender mejor su comportamiento.
- Desarrollar modelos de machine learning que permitan predecir comportamientos clave del clima y entender como predecir las variables objetivo.
- Evaluar la importancia de las diferentes variables en la predicción de los comportamientos de los clientes.
Carga de dataset y dependencias¶
! pip install imblearn
Requirement already satisfied: imblearn in c:\python311\lib\site-packages (0.0) Requirement already satisfied: imbalanced-learn in c:\python311\lib\site-packages (from imblearn) (0.12.2) Requirement already satisfied: numpy>=1.17.3 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (1.24.3) Requirement already satisfied: scipy>=1.5.0 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (1.10.1) Requirement already satisfied: scikit-learn>=1.0.2 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (1.2.2) Requirement already satisfied: joblib>=1.1.1 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (1.2.0) Requirement already satisfied: threadpoolctl>=2.0.0 in c:\python311\lib\site-packages (from imbalanced-learn->imblearn) (3.1.0)
[notice] A new release of pip available: 22.3 -> 24.1 [notice] To update, run: python.exe -m pip install --upgrade pip
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.impute import SimpleImputer
from sklearn.impute import KNNImputer
from sklearn.preprocessing import OneHotEncoder
from imblearn.over_sampling import SMOTE
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import pandas as pd
#Carga de dataset
df = pd.read_csv('temperatura.csv', sep=',', low_memory=False)
df.head()
| Date | Location | MinTemp | MaxTemp | Rainfall | Evaporation | Sunshine | WindGustDir | WindGustSpeed | WindDir9am | ... | Humidity3pm | Pressure9am | Pressure3pm | Cloud9am | Cloud3pm | Temp9am | Temp3pm | RainToday | RISK_MM | RainTomorrow | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 2008-12-01 | Albury | 13.4 | 22.9 | 0.6 | NaN | NaN | W | 44.0 | W | ... | 22.0 | 1007.7 | 1007.1 | 8.0 | NaN | 16.9 | 21.8 | No | 0.0 | No |
| 1 | 2008-12-02 | Albury | 7.4 | 25.1 | 0.0 | NaN | NaN | WNW | 44.0 | NNW | ... | 25.0 | 1010.6 | 1007.8 | NaN | NaN | 17.2 | 24.3 | No | 0.0 | No |
| 2 | 2008-12-03 | Albury | 12.9 | 25.7 | 0.0 | NaN | NaN | WSW | 46.0 | W | ... | 30.0 | 1007.6 | 1008.7 | NaN | 2.0 | 21.0 | 23.2 | No | 0.0 | No |
| 3 | 2008-12-04 | Albury | 9.2 | 28.0 | 0.0 | NaN | NaN | NE | 24.0 | SE | ... | 16.0 | 1017.6 | 1012.8 | NaN | NaN | 18.1 | 26.5 | No | 1.0 | No |
| 4 | 2008-12-05 | Albury | 17.5 | 32.3 | 1.0 | NaN | NaN | W | 41.0 | ENE | ... | 33.0 | 1010.8 | 1006.0 | 7.0 | 8.0 | 17.8 | 29.7 | No | 0.2 | No |
5 rows × 24 columns
df.info(max_cols=30)
<class 'pandas.core.frame.DataFrame'> RangeIndex: 142193 entries, 0 to 142192 Data columns (total 24 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 142193 non-null object 1 Location 142193 non-null object 2 MinTemp 141556 non-null float64 3 MaxTemp 141871 non-null float64 4 Rainfall 140787 non-null float64 5 Evaporation 81350 non-null float64 6 Sunshine 74377 non-null float64 7 WindGustDir 132863 non-null object 8 WindGustSpeed 132923 non-null float64 9 WindDir9am 132180 non-null object 10 WindDir3pm 138415 non-null object 11 WindSpeed9am 140845 non-null float64 12 WindSpeed3pm 139563 non-null float64 13 Humidity9am 140419 non-null float64 14 Humidity3pm 138583 non-null float64 15 Pressure9am 128179 non-null float64 16 Pressure3pm 128212 non-null float64 17 Cloud9am 88536 non-null float64 18 Cloud3pm 85099 non-null float64 19 Temp9am 141289 non-null float64 20 Temp3pm 139467 non-null float64 21 RainToday 140787 non-null object 22 RISK_MM 142193 non-null float64 23 RainTomorrow 142193 non-null object dtypes: float64(17), object(7) memory usage: 26.0+ MB
Fase 2: Data Understanding¶
Análisis estadístico¶
df.describe().T
| count | mean | std | min | 25% | 50% | 75% | max | |
|---|---|---|---|---|---|---|---|---|
| MinTemp | 141556.0 | 12.186400 | 6.403283 | -8.5 | 7.6 | 12.0 | 16.8 | 33.9 |
| MaxTemp | 141871.0 | 23.226784 | 7.117618 | -4.8 | 17.9 | 22.6 | 28.2 | 48.1 |
| Rainfall | 140787.0 | 2.349974 | 8.465173 | 0.0 | 0.0 | 0.0 | 0.8 | 371.0 |
| Evaporation | 81350.0 | 5.469824 | 4.188537 | 0.0 | 2.6 | 4.8 | 7.4 | 145.0 |
| Sunshine | 74377.0 | 7.624853 | 3.781525 | 0.0 | 4.9 | 8.5 | 10.6 | 14.5 |
| WindGustSpeed | 132923.0 | 39.984292 | 13.588801 | 6.0 | 31.0 | 39.0 | 48.0 | 135.0 |
| WindSpeed9am | 140845.0 | 14.001988 | 8.893337 | 0.0 | 7.0 | 13.0 | 19.0 | 130.0 |
| WindSpeed3pm | 139563.0 | 18.637576 | 8.803345 | 0.0 | 13.0 | 19.0 | 24.0 | 87.0 |
| Humidity9am | 140419.0 | 68.843810 | 19.051293 | 0.0 | 57.0 | 70.0 | 83.0 | 100.0 |
| Humidity3pm | 138583.0 | 51.482606 | 20.797772 | 0.0 | 37.0 | 52.0 | 66.0 | 100.0 |
| Pressure9am | 128179.0 | 1017.653758 | 7.105476 | 980.5 | 1012.9 | 1017.6 | 1022.4 | 1041.0 |
| Pressure3pm | 128212.0 | 1015.258204 | 7.036677 | 977.1 | 1010.4 | 1015.2 | 1020.0 | 1039.6 |
| Cloud9am | 88536.0 | 4.437189 | 2.887016 | 0.0 | 1.0 | 5.0 | 7.0 | 9.0 |
| Cloud3pm | 85099.0 | 4.503167 | 2.720633 | 0.0 | 2.0 | 5.0 | 7.0 | 9.0 |
| Temp9am | 141289.0 | 16.987509 | 6.492838 | -7.2 | 12.3 | 16.7 | 21.6 | 40.2 |
| Temp3pm | 139467.0 | 21.687235 | 6.937594 | -5.4 | 16.6 | 21.1 | 26.4 | 46.7 |
| RISK_MM | 142193.0 | 2.360682 | 8.477969 | 0.0 | 0.0 | 0.0 | 0.8 | 371.0 |
Tipos de datos¶
1. Análisis de los tipos de datos¶
data_types_counts = df.dtypes.value_counts()
plt.figure(figsize=(4, 5))
ax = data_types_counts.plot(kind='bar', rot=0, color='purple')
for p in ax.patches:
ax.annotate(str(p.get_height()), (p.get_x() + p.get_width() / 2., p.get_height()),
ha='center', va='center', xytext=(0, 5), textcoords='offset points')
plt.xlabel('Tipo de Dato')
plt.ylabel('Cantidad')
plt.title('Cantidad de cada Tipo de Dato en el DataFrame')
plt.show()
Recomendación: Transformar las variables de tipo object a un tipo de dato más adecuado para su análisis.
2. Revisión de datos tipo object¶
df_object = df.select_dtypes(include=['object'])
print('Columnas de tipo object')
for col in df_object.columns:
print(f"Columna {col} valores únicos -> {df_object[col].unique()[:5]}")
Columnas de tipo object Columna Date valores únicos -> ['2008-12-01' '2008-12-02' '2008-12-03' '2008-12-04' '2008-12-05'] Columna Location valores únicos -> ['Albury' 'BadgerysCreek' 'Cobar' 'CoffsHarbour' 'Moree'] Columna WindGustDir valores únicos -> ['W' 'WNW' 'WSW' 'NE' 'NNW'] Columna WindDir9am valores únicos -> ['W' 'NNW' 'SE' 'ENE' 'SW'] Columna WindDir3pm valores únicos -> ['WNW' 'WSW' 'E' 'NW' 'W'] Columna RainToday valores únicos -> ['No' 'Yes' nan] Columna RainTomorrow valores únicos -> ['No' 'Yes']
# Obtener los valores únicos de la columna 'ubicacion'
valores_unicos = df['Location'].unique()
# Imprimir los valores únicos
print(valores_unicos)
['Albury' 'BadgerysCreek' 'Cobar' 'CoffsHarbour' 'Moree' 'Newcastle' 'NorahHead' 'NorfolkIsland' 'Penrith' 'Richmond' 'Sydney' 'SydneyAirport' 'WaggaWagga' 'Williamtown' 'Wollongong' 'Canberra' 'Tuggeranong' 'MountGinini' 'Ballarat' 'Bendigo' 'Sale' 'MelbourneAirport' 'Melbourne' 'Mildura' 'Nhil' 'Portland' 'Watsonia' 'Dartmoor' 'Brisbane' 'Cairns' 'GoldCoast' 'Townsville' 'Adelaide' 'MountGambier' 'Nuriootpa' 'Woomera' 'Albany' 'Witchcliffe' 'PearceRAAF' 'PerthAirport' 'Perth' 'SalmonGums' 'Walpole' 'Hobart' 'Launceston' 'AliceSprings' 'Darwin' 'Katherine' 'Uluru']
Recomendaciones:
- Date: Se recomienda excluir esta columna del análisis debido a que como valores únicos contamos con solo 5 fechas y además no serán relevantes para la etapa de modelado.
- Location: Realizar One-Hot Encoding.
- WindGustDir, WindDir9am y WindDir3pm: Realziar One-Hot Encoding con los valores conocidos.
- RainToday: Realizar un tratamiento especial para los trabajar datos nulos completando con la moda o eliminandolos. Sumado a lo anterior realizar la conversión a binario.
- RainTomorrow: Se trata de una de nuestras variables objetvo y se recomienda realizar la conversión a binario.
3. Búsqueda de valores nulos¶
3.1 Datos Nulos porcentual¶
#Saber porcentaje de valores nulos por columna
null_counts = df.isnull().sum()
null_counts[null_counts > 0].sort_values(ascending=True) / df.shape[0] * 100
MaxTemp 0.226453 MinTemp 0.447983 Temp9am 0.635756 WindSpeed9am 0.948007 Rainfall 0.988797 RainToday 0.988797 Humidity9am 1.247600 WindSpeed3pm 1.849599 Temp3pm 1.917113 Humidity3pm 2.538803 WindDir3pm 2.656952 WindGustSpeed 6.519308 WindGustDir 6.561504 WindDir9am 7.041838 Pressure3pm 9.832411 Pressure9am 9.855619 Cloud9am 37.735332 Cloud3pm 40.152469 Evaporation 42.789026 Sunshine 47.692924 dtype: float64
3.2 Datos Nulos por cantidad de valores¶
null_counts[null_counts > 0].sort_values(ascending=False)
Sunshine 67816 Evaporation 60843 Cloud3pm 57094 Cloud9am 53657 Pressure9am 14014 Pressure3pm 13981 WindDir9am 10013 WindGustDir 9330 WindGustSpeed 9270 WindDir3pm 3778 Humidity3pm 3610 Temp3pm 2726 WindSpeed3pm 2630 Humidity9am 1774 RainToday 1406 Rainfall 1406 WindSpeed9am 1348 Temp9am 904 MinTemp 637 MaxTemp 322 dtype: int64
3.3 Análisis de columnas con más de 10% de valores nulos¶
- Lo primero que haremos es revisar los valores únicos para descartar que los valores nulos representen algo en cada columna y entender los posibles valores
columns_of_interest = [
'MaxTemp', 'MinTemp', 'Temp9am', 'WindSpeed9am',
'Rainfall', 'RainToday', 'Humidity9am',
'WindSpeed3pm', 'Temp3pm', 'Humidity3pm', 'WindDir3pm',
'WindGustSpeed','WindGustDir','WindDir9am','Pressure3pm','Pressure9am'
]
for column in columns_of_interest:
unique_values = df[column].unique().tolist()
print(f"Valores únicos de la columna {column} -> {unique_values}")
Valores únicos de la columna MaxTemp -> [22.9, 25.1, 25.7, 28.0, 32.3, 29.7, 25.0, 26.7, 31.9, 30.1, 30.4, 21.7, 18.6, 21.0, 27.7, 20.9, 22.5, 25.6, 29.3, 33.0, 31.8, 30.9, 32.4, 33.9, 32.7, 27.2, 24.2, 24.4, 26.5, 23.9, 28.8, 34.6, 35.8, 37.9, 38.9, 28.3, 28.4, 30.8, 32.0, 34.7, 37.7, 43.0, 32.2, 36.6, 39.9, 38.1, 34.0, 35.2, 30.6, 34.3, 38.4, 38.2, 40.7, 41.5, 42.9, 42.7, 43.1, 38.3, 36.9, 41.2, 42.2, 44.8, 40.2, 31.2, 27.3, 21.6, 29.0, 29.2, 31.3, 31.1, 29.1, 31.7, 33.2, 29.6, 32.6, 34.5, 30.3, 22.1, 22.0, 24.0, 27.9, 30.2, 30.5, 25.8, 27.0, 19.7, 21.9, 25.3, 33.5, 33.6, 30.0, 31.6, 22.3, 29.8, 27.6, 28.9, 29.9, 32.1, 28.1, 21.4, 24.9, 25.4, 20.0, 23.4, 22.7, 16.2, 15.8, 12.9, 11.5, 14.5, 12.2, 16.5, 17.0, 19.2, 18.9, 19.1, 18.8, 19.3, 18.4, 19.0, 20.5, 19.5, 17.7, 18.5, 15.1, 16.3, 16.6, 16.4, 15.6, 19.8, 21.1, 20.3, 18.1, 15.7, 16.8, 17.1, 14.3, 13.4, 17.4, 16.1, 10.5, 11.6, 12.0, 8.8, 9.6, 8.2, 12.4, 14.9, 15.9, 14.7, 15.3, 17.3, 15.5, 14.1, 13.7, 11.9, 12.3, 13.3, 13.2, 12.1, 12.5, 13.8, 15.0, 13.5, 13.1, 11.0, 12.6, 14.4, 9.8, 12.7, 13.9, 14.8, 15.2, 17.5, 13.6, 12.8, 16.7, 17.9, 11.1, 14.2, 20.7, 16.9, 17.6, 24.7, 17.8, 17.2, 20.4, 20.6, 20.2, 18.2, 18.7, 23.3, 26.6, 27.1, 23.1, 24.1, 26.8, 26.9, 24.3, 23.2, 33.4, 36.0, 35.1, 32.8, 35.4, 36.3, 39.7, 23.6, 32.9, 26.2, 26.4, 31.5, 27.5, 30.7, 27.4, 22.6, 38.6, 40.3, 33.7, 35.9, 36.8, 33.8, 36.4, 39.8, 42.4, 25.2, 37.3, 41.8, 34.4, 36.5, 35.6, 26.1, 28.5, 31.0, 26.3, nan, 25.5, 22.4, 28.6, 31.4, 28.7, 24.8, 19.9, 23.5, 25.9, 23.0, 10.2, 14.0, 8.4, 8.3, 9.4, 10.9, 10.3, 10.8, 14.6, 15.4, 10.0, 10.1, 11.8, 16.0, 10.4, 13.0, 11.7, 10.7, 19.6, 20.1, 20.8, 23.7, 18.0, 21.8, 22.2, 24.5, 29.4, 21.2, 32.5, 28.2, 21.5, 22.8, 11.2, 19.4, 18.3, 9.2, 9.3, 21.3, 23.8, 26.0, 24.6, 27.8, 33.1, 34.9, 36.1, 36.2, 35.3, 35.5, 9.7, 10.6, 11.3, 11.4, 36.7, 37.4, 43.4, 42.0, 40.4, 39.2, 38.8, 37.0, 35.7, 37.1, 29.5, 37.6, 40.5, 39.0, 43.6, 42.6, 34.2, 33.3, 40.6, 41.7, 41.6, 41.1, 40.1, 8.7, 39.6, 34.1, 9.9, 8.6, 9.1, 6.8, 9.5, 9.0, 37.2, 34.8, 40.0, 35.0, 38.0, 39.5, 40.9, 38.5, 7.5, 39.3, 42.5, 43.7, 37.8, 38.7, 41.9, 39.4, 41.4, 37.5, 45.8, 41.0, 39.1, 40.8, 42.8, 45.1, 44.4, 43.5, 42.1, 46.4, 43.9, 45.4, 41.3, 44.3, 46.0, 43.8, 43.2, 45.2, 8.5, 42.3, 7.8, 45.7, 46.6, 47.3, 44.5, 44.1, 44.0, 43.3, 46.5, 44.9, 46.9, 45.3, 44.6, 47.0, 8.9, 8.1, 7.6, 6.3, 8.0, 6.6, 45.5, 4.1, 7.7, 7.1, 7.9, 7.0, 7.3, 2.6, 7.4, 6.2, 7.2, 6.0, 4.9, -1.7, 0.0, 2.4, 5.3, 2.3, 5.7, 5.2, 5.5, 4.7, 6.5, 2.5, 2.7, 3.4, 2.9, 5.0, 3.2, 0.1, -0.1, -2.2, -0.6, 0.6, 2.2, 4.0, 3.5, 3.0, 4.2, 3.3, 3.9, 0.4, 5.9, -0.7, -1.8, -0.2, -1.3, 1.8, 3.1, 1.6, 0.3, 1.2, -0.5, 1.0, 0.5, 0.2, 1.9, 2.0, 5.1, 2.8, 6.7, 0.9, 3.8, 4.3, -2.4, -0.3, 4.6, 6.9, -2.5, 2.1, 1.4, 5.6, 3.6, 4.4, -2.7, -1.0, 5.8, -1.4, -0.8, -2.0, 4.5, 1.7, -0.9, -2.1, -1.5, -3.1, 1.1, -1.2, 4.8, 6.1, 6.4, 3.7, -1.1, 1.5, 5.4, 1.3, 0.8, -2.3, -3.7, -2.9, -0.4, -1.9, -3.8, 0.7, -4.1, -3.2, -3.0, -4.8, 44.2, 46.8, 46.7, 45.0, 46.3, 44.7, 45.6, 46.2, 48.1, 46.1] Valores únicos de la columna MinTemp -> [13.4, 7.4, 12.9, 9.2, 17.5, 14.6, 14.3, 7.7, 9.7, 13.1, 15.9, 12.6, 9.8, 14.1, 13.5, 11.2, 11.5, 17.1, 20.5, 15.3, 16.2, 16.9, 20.1, 19.7, 12.5, 12.0, 11.3, 9.6, 10.5, 12.3, 13.7, 16.1, 14.0, 17.0, 17.3, 17.2, 17.4, 19.8, 14.9, 13.9, 18.6, 19.3, 24.4, 18.8, 20.8, 15.7, 18.5, 20.4, 21.8, 22.3, 22.0, 28.0, 21.5, 21.7, 23.5, 28.3, 18.4, 12.4, 13.3, 18.0, 18.7, 15.5, 8.9, 15.0, 15.4, 16.0, 12.8, 13.2, 13.8, 7.6, 8.3, 11.0, 20.9, 16.4, 10.0, 8.8, 8.4, 9.3, 14.4, 10.8, 10.1, 9.1, 10.4, 12.2, 10.7, 7.8, 8.1, 7.5, 8.2, 11.6, 13.0, 9.9, 3.5, 6.6, 7.0, 5.7, 6.2, 6.0, 10.6, 8.6, 4.5, 5.4, 2.1, 1.8, 7.2, 4.6, 4.2, 5.2, 4.1, 3.2, 4.3, 3.7, 3.6, 6.9, 10.3, 3.0, 2.6, 5.1, 4.4, 4.7, 6.7, 8.0, 2.2, 1.7, 2.8, 9.0, 6.3, -2.0, -1.3, 2.0, 0.5, 1.2, 0.6, 0.9, 5.0, 3.9, 3.4, 0.0, -1.5, -1.7, -0.4, 0.1, 4.8, 5.9, 2.9, -0.6, -0.3, -1.0, 0.8, -0.1, 1.3, 3.3, 6.5, -0.8, 1.9, 6.8, 2.7, 1.6, 5.5, 7.3, 0.2, 5.8, 7.1, 1.1, 1.0, 6.1, nan, 5.3, 4.0, 11.7, 8.5, 3.8, 6.4, 9.5, 14.5, 15.6, 17.8, 16.7, 18.1, 12.1, 11.4, 18.3, 11.9, 21.0, 11.1, 18.2, 14.2, 11.8, 13.6, 12.7, 15.1, 22.9, 17.6, 21.1, 19.4, 14.8, 16.3, 19.6, 20.6, 24.5, 22.6, 16.8, 8.7, 19.2, 24.7, 17.7, 15.2, 18.9, 17.9, 19.5, 20.3, 23.0, 22.5, 20.2, 16.5, 5.6, 3.1, 1.4, 10.2, 9.4, 0.4, 4.9, 1.5, 2.3, 0.7, -0.5, 2.5, -1.2, 0.3, 2.4, 14.7, 10.9, 16.6, 21.3, 23.2, 21.6, 22.1, 24.0, 19.9, 20.7, 21.9, -0.7, -1.1, -1.4, -0.2, -1.6, 15.8, 19.1, 20.0, -2.5, -1.8, 7.9, 21.2, 22.2, 23.7, 25.2, 19.0, -0.9, -2.1, -2.8, 26.0, -2.4, 26.8, 23.4, 22.8, 22.4, 24.6, 23.9, -3.0, 23.1, 23.6, 21.4, -1.9, 25.1, 24.2, 27.1, 23.3, 24.9, 25.4, 23.8, 27.0, 26.2, 25.0, 24.8, 27.6, 24.1, 27.2, 29.1, 28.9, 25.3, 27.4, 28.8, 27.3, 26.1, 26.5, 22.7, 25.7, 24.3, 29.3, 27.7, 26.3, 25.8, 29.4, 25.6, 26.7, 26.6, 28.1, 27.8, 28.5, 25.5, 26.9, 26.4, 27.5, 28.7, 29.7, 25.9, -2.3, -3.3, -2.2, -3.2, 29.0, 28.6, -3.8, -4.8, -3.1, -2.7, -2.6, -2.9, -4.7, -3.6, -3.5, -3.4, -5.3, -3.7, -5.8, -5.0, -4.5, -4.3, -3.9, -4.2, -4.0, -6.9, -6.5, -5.5, -5.2, -6.3, -4.4, -8.0, -6.7, -4.9, -5.4, -6.1, -4.6, -6.0, -6.6, -5.1, -5.6, -6.8, -7.6, -7.0, -4.1, -5.7, -6.2, -8.2, -5.9, -8.5, -7.1, -6.4, -7.5, -7.2, -7.8, -7.3, 30.5, 29.8, 31.9, 28.4, 28.2, 27.9, 30.7, 33.9, 29.2, 29.9, 31.4, 31.8, 29.5, 31.2, 29.6, 30.3, 31.0, 30.2] Valores únicos de la columna Temp9am -> [16.9, 17.2, 21.0, 18.1, 17.8, 20.6, 16.3, 18.3, 20.1, 20.4, 15.9, 17.4, 15.8, 17.3, 18.0, 15.5, 19.1, 24.5, 23.8, 20.9, 21.5, 23.2, 26.6, 24.6, 21.6, 12.5, 19.7, 14.9, 17.1, 20.7, 22.4, 23.1, 25.2, 17.9, 20.2, 22.8, 24.2, 24.3, 25.6, 27.6, 16.0, 22.0, 26.8, 27.3, 26.1, 23.3, 21.2, 23.4, 25.8, 28.2, 29.0, 29.2, 29.9, 32.4, 28.8, 27.2, 25.5, 26.5, 28.7, 29.6, 34.5, 18.7, 16.7, 17.0, 19.2, 21.4, 22.1, 19.3, 15.0, 20.0, 22.2, 23.0, 15.6, 13.9, 12.6, 13.3, 17.6, 18.6, 19.0, 19.9, 12.7, 12.2, 12.1, 14.7, 18.8, 15.4, 16.2, 16.5, 14.0, 16.6, 18.4, 12.9, 13.8, 15.1, 16.4, 16.1, 20.5, 9.6, 12.4, 14.1, 11.2, 9.5, 7.6, 10.1, 8.2, 7.9, 7.2, 10.6, 10.3, 10.0, 8.3, 11.0, 9.4, 11.7, 8.5, 9.1, 7.5, 13.0, 7.0, 8.8, 7.4, 11.9, 11.6, 13.6, 7.1, 10.2, 8.0, 9.2, 11.3, 4.7, 6.8, 4.9, 2.2, 1.9, 5.9, 6.5, 5.4, 6.6, 5.6, 6.9, 8.4, 9.8, 13.5, 7.8, 2.3, 2.4, 3.3, 3.8, 4.8, 8.1, 9.0, 4.5, 3.2, 3.7, 2.5, 4.4, 4.2, 9.3, 8.9, 10.5, 9.9, 5.7, 2.0, 14.8, 6.7, 6.0, 5.5, 11.1, 5.8, 10.8, 13.2, 7.7, 9.7, 8.6, 8.7, 10.9, 14.3, 11.5, 13.1, 15.2, 11.8, 13.4, 14.4, 23.9, 17.5, 24.7, 21.7, 24.1, 19.5, 27.8, 16.8, 20.3, 18.9, 15.7, 12.8, 21.8, 20.8, 32.1, 24.4, 26.0, 28.1, 21.3, 26.4, 29.1, 29.4, 25.1, 27.7, 18.5, 25.0, 22.9, 23.5, 26.3, 22.6, 25.9, 19.6, 22.3, 19.8, 14.2, 17.7, 19.4, 18.2, 14.6, 15.3, 10.4, 10.7, 6.4, 6.3, 5.1, 6.2, 5.3, 4.1, 3.4, 6.1, 2.8, 3.1, 3.0, 5.0, 2.9, 5.2, 4.0, 4.6, 4.3, 7.3, 11.4, 13.7, 24.0, 22.5, 21.9, 26.7, 24.9, 25.3, 21.1, 25.4, 24.8, 14.5, 3.5, 3.6, 3.9, 2.6, 12.0, 22.7, 0.3, 27.5, 29.5, 23.6, 30.7, 29.7, 27.0, 23.7, 12.3, nan, 28.6, 26.9, 31.8, 28.0, 30.8, 28.4, 25.7, 27.4, 26.2, 33.7, 27.9, 30.2, 28.3, 2.7, 29.3, 29.8, 1.6, 30.4, 37.6, 34.2, 31.3, 33.6, 31.5, 31.4, 28.9, 30.1, 32.0, 32.6, 35.6, 31.6, 31.2, 30.0, 34.3, 31.1, 37.3, 27.1, 34.4, 33.0, 33.9, 32.9, 34.1, 28.5, 35.7, 31.0, 30.3, 32.3, 35.1, 34.8, 34.0, 37.7, 30.9, 32.2, 33.4, 33.2, 32.7, 30.6, 31.7, 35.2, 30.5, 33.5, 36.8, 34.9, 33.1, 36.3, 32.5, 31.9, 32.8, 35.5, 36.4, 37.5, 35.9, 0.8, 0.9, 36.5, 37.2, 33.3, 0.6, 1.0, 1.7, 2.1, 1.2, 1.8, 0.0, 1.3, 1.5, 0.5, 0.4, 0.2, 1.4, 0.1, -0.9, 0.7, -0.7, -0.2, -0.3, -1.1, 1.1, -1.0, -1.2, -1.3, -0.5, -0.6, -0.4, -0.8, -3.1, -0.1, -1.4, -1.7, -2.3, -2.8, -3.4, -5.9, -2.5, -4.1, -1.6, -2.2, -2.4, -2.9, -2.1, -3.2, -2.0, -1.8, -4.2, -3.3, -4.3, -3.7, -3.6, -5.5, -4.0, -1.9, -4.8, -2.7, -5.2, -5.3, -1.5, -3.9, -3.0, -3.8, -4.4, -2.6, -6.2, -3.5, -4.5, -5.6, -7.0, -7.2, 36.0, 35.4, 34.6, 33.8, 36.9, 35.3, 36.1, 38.3, 37.4, 34.7, 38.6, 35.8, 37.9, 35.0, 40.2, 37.0, 39.4, 39.0, 38.2, 36.2, 38.9, 36.6, 39.1, 38.0] Valores únicos de la columna WindSpeed9am -> [20.0, 4.0, 19.0, 11.0, 7.0, 6.0, 15.0, 17.0, 28.0, 24.0, nan, 9.0, 0.0, 13.0, 2.0, 26.0, 30.0, 22.0, 35.0, 37.0, 31.0, 33.0, 48.0, 39.0, 44.0, 41.0, 46.0, 43.0, 56.0, 83.0, 74.0, 52.0, 65.0, 50.0, 130.0, 54.0, 61.0, 57.0, 59.0, 87.0, 67.0, 63.0, 69.0, 72.0] Valores únicos de la columna Rainfall -> [0.6, 0.0, 1.0, 0.2, 1.4, 2.2, 15.6, 3.6, nan, 16.8, 10.6, 1.2, 0.8, 6.4, 0.4, 3.0, 5.8, 11.6, 1.8, 8.6, 12.6, 8.4, 6.2, 20.0, 21.0, 3.2, 4.8, 4.2, 8.0, 14.4, 4.6, 2.0, 5.6, 1.6, 6.0, 4.4, 5.4, 5.0, 7.8, 6.8, 9.8, 3.8, 2.4, 5.2, 6.6, 13.4, 10.2, 28.8, 7.0, 25.8, 9.4, 12.4, 52.2, 20.6, 66.0, 11.0, 17.0, 10.4, 28.0, 21.4, 18.6, 7.2, 8.2, 10.8, 15.4, 9.6, 4.0, 21.8, 20.8, 24.8, 10.0, 11.4, 19.0, 22.2, 32.8, 3.4, 50.8, 52.6, 19.2, 18.8, 14.8, 12.0, 18.4, 25.6, 35.0, 14.2, 13.8, 2.6, 99.2, 51.0, 39.8, 28.2, 12.2, 12.8, 11.8, 19.8, 17.4, 8.8, 16.2, 14.6, 2.8, 30.8, 28.4, 34.8, 44.0, 14.0, 16.6, 9.0, 26.8, 38.4, 104.2, 36.6, 34.2, 29.4, 27.2, 11.2, 13.2, 33.4, 7.6, 24.6, 7.4, 16.0, 19.4, 53.4, 15.0, 33.6, 17.2, 37.4, 13.0, 31.0, 9.2, 66.2, 36.4, 41.0, 24.4, 27.0, 46.8, 15.8, 35.8, 22.4, 16.4, 15.2, 23.0, 22.8, 28.6, 46.0, 24.2, 22.0, 18.0, 31.2, 21.2, 36.0, 23.4, 32.0, 46.4, 13.6, 42.0, 33.8, 25.4, 20.4, 22.6, 43.2, 61.4, 48.2, 48.6, 18.2, 67.8, 39.2, 31.8, 82.4, 35.4, 116.0, 30.6, 17.8, 38.2, 30.2, 24.0, 47.0, 42.4, 33.0, 40.0, 44.2, 34.6, 30.4, 38.8, 83.6, 50.2, 26.2, 38.0, 31.6, 27.8, 29.8, 17.6, 100.2, 109.2, 23.6, 32.6, 21.6, 54.0, 39.6, 26.0, 34.0, 49.4, 37.0, 29.2, 68.0, 33.2, 27.4, 39.0, 38.6, 43.0, 4.5, 29.1, 2.9, 1.3, 30.0, 63.6, 189.0, 58.6, 59.0, 20.2, 42.8, 76.0, 19.6, 55.8, 70.0, 71.2, 141.8, 96.0, 371.0, 58.0, 67.0, 80.6, 56.6, 45.2, 59.4, 42.6, 34.4, 90.0, 128.0, 61.2, 23.8, 27.6, 73.8, 72.2, 105.4, 40.4, 102.0, 44.4, 48.0, 63.8, 36.8, 5.5, 25.2, 103.4, 127.6, 63.2, 52.4, 25.0, 55.0, 56.8, 70.8, 62.4, 112.0, 153.2, 45.8, 97.0, 51.8, 86.4, 0.5, 159.8, 208.5, 172.2, 0.9, 2.5, 0.3, 1.7, 3.3, 51.2, 106.4, 147.8, 45.6, 59.6, 29.0, 11.7, 75.0, 76.4, 64.0, 53.2, 100.4, 0.1, 65.8, 8.5, 32.4, 157.8, 4.1, 113.8, 0.7, 3.1, 1.5, 32.2, 32.7, 10.1, 11.1, 96.1, 49.8, 219.6, 109.4, 3.5, 26.4, 29.6, 36.2, 37.6, 43.8, 41.5, 50.6, 142.8, 106.2, 104.8, 2.7, 31.1, 13.9, 71.0, 90.6, 64.8, 47.6, 51.4, 26.6, 48.8, 37.2, 39.4, 113.0, 74.4, 92.8, 40.2, 76.8, 54.6, 44.8, 44.6, 50.0, 22.7, 20.9, 59.8, 45.4, 147.2, 35.2, 71.4, 31.4, 23.7, 42.2, 75.6, 41.8, 43.6, 4.9, 35.6, 26.5, 49.0, 33.9, 30.7, 5.3, 10.7, 64.1, 50.4, 45.5, 6.9, 68.8, 77.6, 89.8, 69.8, 32.5, 62.6, 132.5, 15.7, 22.5, 240.0, 41.2, 6.3, 58.2, 37.9, 29.5, 52.0, 21.5, 216.3, 12.5, 2.3, 51.6, 20.7, 63.4, 74.2, 23.2, 43.4, 56.0, 47.8, 48.4, 69.2, 55.6, 61.8, 73.0, 83.4, 37.8, 126.4, 47.2, 59.2, 120.2, 56.2, 89.0, 76.2, 82.8, 69.6, 72.0, 40.8, 107.4, 71.6, 29.9, 142.2, 79.8, 84.8, 105.6, 57.6, 45.0, 62.2, 111.0, 40.6, 122.6, 54.8, 61.0, 61.6, 156.8, 39.9, 2.1, 1.9, 1.1, 4.7, 5.7, 92.2, 115.4, 101.8, 49.6, 85.6, 81.4, 81.6, 67.6, 58.4, 41.6, 56.4, 111.8, 47.4, 113.4, 74.0, 70.6, 78.4, 68.6, 77.4, 73.2, 99.4, 65.2, 88.2, 57.4, 95.2, 57.0, 119.4, 105.8, 54.4, 41.4, 94.4, 64.4, 93.8, 68.4, 52.8, 85.0, 83.2, 106.0, 60.2, 91.0, 53.6, 104.6, 80.4, 106.8, 88.6, 72.8, 62.8, 46.6, 95.6, 53.0, 54.2, 110.8, 57.8, 12.3, 22.9, 13.3, 134.8, 84.4, 46.2, 64.2, 86.8, 157.6, 166.8, 156.0, 114.4, 81.8, 225.0, 8.7, 91.4, 18.1, 49.2, 60.8, 97.2, 82.6, 78.6, 53.8, 72.6, 139.0, 58.8, 65.0, 79.0, 75.8, 55.2, 192.0, 80.8, 118.0, 96.4, 164.2, 69.4, 75.2, 55.4, 87.0, 93.0, 91.6, 84.2, 87.6, 78.0, 73.4, 102.2, 60.4, 89.4, 107.6, 83.8, 78.2, 88.0, 66.4, 82.2, 155.0, 60.0, 65.6, 63.0, 84.0, 87.4, 83.0, 73.6, 77.2, 79.4, 121.4, 60.6, 93.6, 168.4, 145.0, 94.0, 89.2, 68.2, 182.6, 110.6, 98.0, 278.4, 140.2, 62.0, 121.6, 71.8, 115.8, 79.2, 268.6, 183.0, 109.6, 128.2, 206.2, 136.6, 150.2, 161.6, 109.0, 115.2, 175.2, 247.2, 85.4, 105.2, 74.8, 115.0, 126.0, 84.6, 158.0, 77.8, 64.6, 118.2, 143.8, 118.6, 112.2, 178.2, 183.4, 108.2, 111.2, 128.4, 80.2, 129.0, 105.0, 177.6, 86.2, 236.8, 93.4, 79.6, 206.8, 81.2, 92.6, 165.2, 170.4, 93.2, 98.2, 148.6, 70.2, 144.2, 164.6, 174.6, 70.4, 87.8, 124.8, 120.8, 78.8, 76.6, 11.9, 9.5, 10.5, 7.1, 6.5, 6.1, 34.3, 3.9, 6.7, 12.7, 14.5, 29.3, 23.9, 8.9, 9.1, 13.1, 10.9, 18.5, 65.4, 47.3, 5.9, 19.7, 12.1, 11.5, 7.5, 7.9, 25.3, 17.5, 7.3, 9.9, 15.5, 15.9, 81.0, 95.8, 90.4, 141.2, 162.2, 136.4, 131.4, 132.6, 367.6, 184.6, 182.2, 145.2, 96.8, 74.6, 129.4, 122.8, 109.8, 145.6, 210.6, 117.6, 69.5, 167.0, 69.0] Valores únicos de la columna RainToday -> ['No', 'Yes', nan] Valores únicos de la columna Humidity9am -> [71.0, 44.0, 38.0, 45.0, 82.0, 55.0, 49.0, 48.0, 42.0, 58.0, 89.0, 76.0, 65.0, 50.0, 69.0, 80.0, 47.0, 56.0, 54.0, 41.0, 78.0, 46.0, 43.0, 33.0, 34.0, 36.0, 52.0, 51.0, 40.0, 35.0, 39.0, 60.0, 37.0, 27.0, 32.0, 53.0, 20.0, 66.0, 63.0, 57.0, 62.0, 87.0, 61.0, 59.0, 92.0, 72.0, 67.0, 75.0, 88.0, 68.0, 73.0, 74.0, 83.0, 77.0, 70.0, 81.0, 86.0, 97.0, 99.0, 91.0, 85.0, 93.0, 84.0, 94.0, 79.0, 98.0, 96.0, 95.0, 90.0, 64.0, 29.0, 21.0, 100.0, 24.0, nan, 25.0, 31.0, 18.0, 23.0, 26.0, 28.0, 30.0, 19.0, 22.0, 17.0, 15.0, 9.0, 12.0, 13.0, 16.0, 6.0, 10.0, 14.0, 11.0, 7.0, 8.0, 5.0, 3.0, 2.0, 4.0, 0.0, 1.0] Valores únicos de la columna WindSpeed3pm -> [24.0, 22.0, 26.0, 9.0, 20.0, 17.0, 28.0, 11.0, 6.0, 13.0, 19.0, 30.0, 31.0, 7.0, 15.0, 48.0, 4.0, 33.0, 0.0, 2.0, nan, 37.0, 46.0, 39.0, 50.0, 35.0, 44.0, 41.0, 43.0, 56.0, 61.0, 54.0, 52.0, 83.0, 65.0, 78.0, 57.0, 63.0, 59.0, 74.0, 72.0, 69.0, 76.0, 87.0, 67.0] Valores únicos de la columna Temp3pm -> [21.8, 24.3, 23.2, 26.5, 29.7, 28.9, 24.6, 25.5, 30.2, 28.2, 28.8, 17.0, 15.8, 19.8, 26.2, 18.1, 21.5, 21.0, 27.3, 31.6, 30.8, 29.0, 31.2, 33.0, 32.1, 26.1, 18.2, 22.7, 25.7, 22.1, 33.9, 34.4, 36.8, 38.4, 27.6, 26.6, 29.3, 30.0, 33.2, 35.7, 41.5, 27.1, 25.8, 30.5, 37.7, 36.1, 33.1, 36.5, 36.2, 39.2, 40.1, 41.2, 42.0, 41.9, 37.1, 35.2, 39.7, 41.6, 43.4, 38.5, 29.4, 24.9, 17.3, 28.5, 29.2, 29.5, 27.0, 30.7, 32.7, 26.8, 29.8, 31.3, 33.4, 28.6, 33.6, 28.1, 21.9, 21.4, 22.0, 29.6, 18.8, 23.8, 19.7, 18.3, 20.5, 23.9, 27.2, 32.6, 33.5, 31.4, 19.6, 27.7, 29.9, 30.9, 27.4, 20.3, 21.2, 20.9, 21.6, 23.5, 25.0, 24.4, 23.1, 18.9, 19.4, 22.9, 23.6, 21.3, 22.3, 22.6, 15.1, 14.5, 11.6, 9.4, 14.0, 12.1, 16.1, 16.3, 19.1, 18.5, 18.4, 19.2, 20.2, 17.7, 18.0, 14.6, 15.3, 15.9, 14.7, 18.7, 21.7, 20.8, 19.5, 17.4, 15.6, 16.7, 16.8, 13.4, 13.0, 16.5, 10.2, 11.5, 11.4, 7.9, 9.7, 8.8, 15.5, 13.9, 15.4, 14.9, 16.4, 13.6, 15.2, 13.7, 11.3, 12.3, 13.1, 11.7, 12.6, 12.0, 12.4, 14.3, 13.2, 10.1, 12.5, 12.8, 14.2, 11.2, 13.5, 17.6, 12.9, 10.8, 9.6, 7.3, 12.7, 13.3, 16.6, 11.1, 14.4, 16.2, 17.5, 10.7, 16.0, 24.0, 17.1, 20.7, 17.2, 20.6, 14.8, 10.0, 15.7, 17.8, 19.0, 14.1, 10.9, 19.3, 25.3, 25.4, 24.8, 23.4, 28.4, 30.3, 31.1, 32.8, 33.8, 34.9, 34.6, 31.7, 35.4, 39.0, 36.4, 25.6, 32.0, 25.2, 24.7, 28.7, 30.6, 26.0, 32.5, 36.9, 30.4, 35.9, 37.5, 27.5, 34.1, 35.1, 28.0, 31.8, 35.3, 38.6, 40.9, 41.1, 19.9, 36.0, 24.1, 34.3, 39.1, 34.7, 34.8, 30.1, 32.9, 26.4, 24.2, 20.1, 21.1, 22.8, 31.5, 26.9, 29.1, 28.3, 25.1, 23.0, 22.4, 27.9, 18.6, 16.9, 13.8, 15.0, 8.9, 11.0, 11.8, 8.2, 9.1, 10.4, 12.2, 8.7, 11.9, 22.5, 24.5, 36.7, 37.3, 38.8, 26.7, 8.6, 20.4, 9.0, 10.3, 10.6, 8.0, 8.1, 10.5, 9.8, 9.5, 9.9, 17.9, 22.2, 23.3, 23.7, 26.3, nan, 25.9, 35.0, 34.2, 34.5, 32.4, 27.8, 20.0, 7.0, 35.8, 39.3, 42.4, 40.7, 38.2, 40.6, 35.6, 34.0, 36.3, 32.3, 9.2, 9.3, 8.3, 31.9, 41.7, 38.9, 31.0, 37.2, 40.8, 40.2, 38.3, 8.4, 8.5, 6.7, 32.2, 37.0, 7.6, 6.4, 7.7, 33.3, 39.5, 37.6, 42.3, 33.7, 35.5, 7.5, 7.4, 38.0, 39.8, 37.8, 39.6, 40.3, 36.6, 42.2, 37.9, 43.7, 38.7, 41.0, 43.5, 43.3, 38.1, 43.0, 41.4, 40.0, 40.4, 37.4, 39.9, 43.2, 40.5, 44.8, 42.9, 42.6, 42.1, 42.7, 43.1, 39.4, 6.9, 44.0, 45.2, 45.8, 41.3, 42.8, 46.7, 45.3, 44.1, 42.5, 43.8, 46.2, 45.9, 44.7, 44.9, 41.8, 6.8, 6.0, 6.6, 43.9, 7.1, 7.8, 7.2, 5.7, 5.1, 6.2, 3.7, 6.5, 6.1, 4.3, 5.4, 5.3, 4.9, 5.6, 2.3, 5.5, 6.3, 5.9, 5.8, 3.4, 3.6, -1.9, -1.3, 1.4, 4.4, 4.5, 2.6, 0.8, 4.8, 1.8, 2.4, 2.7, 4.0, 5.0, -0.3, -2.9, -5.1, -0.4, 0.9, 2.1, 2.9, 1.2, -0.6, 1.9, 5.2, -0.7, -1.0, -1.8, -0.1, -1.6, -0.2, 1.6, 1.3, -1.2, 2.0, 2.8, 0.7, -0.9, 0.3, -1.1, 1.1, 1.0, 0.0, -2.8, -1.4, 0.2, 0.4, -3.1, -2.6, 3.0, 0.6, 4.6, 3.2, 4.2, 3.5, 3.8, 4.1, -1.7, -1.5, 3.3, 2.2, -2.0, -2.2, 2.5, -2.3, 3.9, 3.1, -3.7, 4.7, 1.7, 0.1, 1.5, -3.9, -0.5, -2.7, -3.5, -2.1, 0.5, -2.5, -3.2, -4.1, -3.4, -0.8, -3.0, -4.4, -2.4, -4.0, -4.2, -5.4, -3.8, 44.4, 46.1, 45.4, 43.6, 44.5, 44.3, 45.0] Valores únicos de la columna Humidity3pm -> [22.0, 25.0, 30.0, 16.0, 33.0, 23.0, 19.0, 9.0, 27.0, 91.0, 93.0, 43.0, 28.0, 82.0, 65.0, 32.0, 26.0, 24.0, 17.0, 15.0, 70.0, 12.0, 8.0, 31.0, 20.0, 10.0, 21.0, 39.0, 13.0, 11.0, 69.0, 18.0, 14.0, 35.0, 90.0, 68.0, 74.0, 41.0, 34.0, 78.0, 49.0, 37.0, 42.0, 47.0, 52.0, 29.0, 86.0, 89.0, 62.0, 79.0, 48.0, 46.0, 38.0, 44.0, 51.0, 36.0, 45.0, 40.0, 53.0, 61.0, 59.0, 63.0, 54.0, 57.0, 50.0, 58.0, 75.0, 97.0, 80.0, 95.0, 56.0, 72.0, 60.0, 71.0, 73.0, 81.0, 76.0, 64.0, 87.0, 85.0, 67.0, 55.0, 77.0, 84.0, 7.0, 99.0, 92.0, 66.0, 83.0, 94.0, 96.0, 88.0, nan, 100.0, 98.0, 5.0, 6.0, 1.0, 4.0, 2.0, 3.0, 0.0] Valores únicos de la columna WindDir3pm -> ['WNW', 'WSW', 'E', 'NW', 'W', 'SSE', 'ESE', 'ENE', 'NNW', 'SSW', 'SW', 'SE', 'N', 'S', 'NNE', nan, 'NE'] Valores únicos de la columna WindGustSpeed -> [44.0, 46.0, 24.0, 41.0, 56.0, 50.0, 35.0, 80.0, 28.0, 30.0, 31.0, 61.0, 22.0, 63.0, 43.0, 26.0, 33.0, 57.0, 48.0, 39.0, 37.0, 52.0, 98.0, 54.0, 83.0, nan, 59.0, 70.0, 69.0, 17.0, 20.0, 19.0, 15.0, 13.0, 11.0, 72.0, 85.0, 65.0, 78.0, 107.0, 74.0, 67.0, 94.0, 76.0, 81.0, 87.0, 9.0, 7.0, 89.0, 91.0, 93.0, 102.0, 100.0, 113.0, 117.0, 96.0, 111.0, 106.0, 135.0, 104.0, 120.0, 115.0, 126.0, 109.0, 122.0, 124.0, 130.0, 6.0] Valores únicos de la columna WindGustDir -> ['W', 'WNW', 'WSW', 'NE', 'NNW', 'N', 'NNE', 'SW', 'ENE', 'SSE', 'S', 'NW', 'SE', 'ESE', nan, 'E', 'SSW'] Valores únicos de la columna WindDir9am -> ['W', 'NNW', 'SE', 'ENE', 'SW', 'SSE', 'S', 'NE', nan, 'SSW', 'N', 'WSW', 'ESE', 'E', 'NW', 'WNW', 'NNE'] Valores únicos de la columna Pressure3pm -> [1007.1, 1007.8, 1008.7, 1012.8, 1006.0, 1005.4, 1008.2, 1010.1, 1003.6, 1005.7, 1004.2, 993.0, 1001.8, 1010.3, 1010.4, 1002.2, 1009.7, 1017.1, 1014.8, 1008.1, 1007.6, 1001.7, 1003.4, 1005.1, 1003.2, 1013.1, 1009.2, 1006.7, 1002.7, 1010.9, 1013.7, 1006.8, 1012.1, 1006.9, 1012.7, 1017.4, 1016.2, 1010.6, 1004.8, 1005.9, 997.8, 1003.9, 1014.6, 1014.1, 1011.6, 1011.8, 1010.2, 1010.5, 1007.4, 1004.7, 1002.6, 1005.0, 1003.8, 1006.5, 1008.5, 1011.1, 1017.3, 1019.7, 1016.4, 1013.8, 1013.5, 1007.5, 1004.5, 1010.8, 1012.4, 1013.4, 1015.0, 1012.6, 1004.6, 1009.0, 1012.0, 1014.7, 1015.9, 1018.0, 1018.9, 1008.0, 1013.2, 1013.9, 1013.6, 1014.4, 1019.2, 1017.2, 1020.7, 1020.6, 1019.1, 1019.5, 1019.4, 1018.4, 1012.9, 1019.3, 1016.5, 1019.6, 1023.5, 1023.4, 1017.7, 1020.3, 1020.8, 1018.7, 1009.8, 1016.8, 1020.0, 1020.9, 1021.6, 1015.7, 1002.4, 1000.9, 1003.3, 1018.3, 1021.5, 1023.2, 1024.0, 1025.9, 1027.3, 1028.1, 1024.6, 1023.6, 1025.8, 1021.8, 1022.3, 1022.2, 1018.5, 1011.0, 1021.2, 1019.9, 1020.5, 1021.4, 1022.1, 1028.5, 1029.9, 1029.2, 1026.2, 1020.4, 1017.5, 1015.1, 1006.3, 1008.3, 1023.0, 1013.0, 1009.3, 1027.7, 1028.6, 1027.1, 1018.6, 1005.5, 1006.6, 1009.4, 1001.0, 1005.2, 1009.6, 1014.9, 1019.0, 1023.8, 1015.6, 1007.7, 1005.8, 1009.9, 1014.5, 1019.8, 1006.2, 1025.4, 1022.7, 1023.1, 1025.3, 1024.8, 1022.9, 1020.2, 1016.7, 1008.6, 1010.0, 1015.3, 1006.4, 1027.2, 1022.5, 1014.3, 1013.3, 996.9, 1015.2, 1021.7, 1012.3, 1017.9, 1011.4, 1011.3, 1018.2, 1015.4, 1012.2, 1011.9, 999.2, 1002.9, 1008.4, 1008.8, 1004.9, 1025.7, 1016.9, 999.4, 997.6, 1024.7, 1023.7, 1017.6, 1022.0, 1015.8, 1017.8, 1011.2, 1002.3, 1003.5, 1016.0, 1016.3, 1016.1, 1014.2, 1007.3, 1017.0, 1012.5, 1011.5, 1009.1, 1004.1, 1007.0, 1003.7, 1007.9, 1011.7, 1021.3, 1030.2, 1033.6, 1031.4, 1026.0, 1021.0, 1023.3, 1018.8, 1018.1, 1021.1, 1020.1, 1024.4, 1021.9, 1014.0, 1024.1, 1024.3, 1015.5, 1002.8, 1030.7, 1032.0, 1028.3, 1026.7, 1033.8, 1035.2, 1032.9, 1029.8, 1029.0, 1022.8, 1025.1, 1026.6, 1008.9, 1026.3, 1028.9, 1029.1, 1034.1, 1031.5, 1000.1, 1004.4, 1025.2, 999.0, 1022.6, 1025.0, 1023.9, 982.9, 1007.2, 1002.1, 994.3, 1004.3, 1000.5, 1010.7, 1009.5, 1006.1, 1001.5, 1016.6, 1002.5, 1000.3, 1005.3, 1030.5, 1028.8, 1024.9, 1024.5, 1027.8, 1028.7, 1032.6, 1035.1, 1034.2, 1029.7, 1033.3, 1027.6, 1030.4, 1034.6, 1036.0, 996.2, 1030.9, 1026.1, nan, 1000.7, 995.4, 1002.0, 995.7, 1001.9, 1031.0, 1031.1, 1031.9, 1032.5, 1025.5, 1028.4, 1033.2, 1024.2, 1030.3, 1030.0, 1001.3, 1000.8, 1001.6, 1026.9, 997.2, 998.5, 1026.8, 1027.9, 1028.2, 1029.3, 1022.4, 1027.4, 1029.4, 999.6, 1001.4, 999.1, 994.8, 1001.2, 998.4, 1025.6, 1026.5, 1003.0, 998.9, 998.8, 1026.4, 1027.5, 1030.1, 1032.3, 1032.8, 1005.6, 998.7, 1000.2, 1033.5, 1032.2, 1030.6, 1031.7, 1028.0, 1032.1, 1031.2, 1029.5, 1004.0, 1036.1, 999.5, 993.1, 998.1, 997.5, 1000.0, 995.9, 1034.3, 1033.7, 1031.3, 1032.4, 998.0, 1000.6, 998.2, 1001.1, 999.3, 1003.1, 1034.9, 1036.2, 1032.7, 1031.8, 995.1, 1036.4, 1035.0, 1034.8, 1036.8, 996.4, 1031.6, 997.7, 1027.0, 997.9, 996.7, 999.8, 999.7, 995.3, 994.5, 996.5, 998.3, 1030.8, 993.8, 997.4, 995.8, 1029.6, 1034.0, 993.7, 999.9, 997.1, 1000.4, 1034.7, 991.6, 1034.4, 1033.4, 1035.9, 996.8, 997.0, 1035.6, 995.5, 1034.5, 1035.7, 995.6, 994.9, 996.1, 979.0, 996.0, 995.2, 1033.0, 989.0, 1036.3, 1035.5, 993.4, 994.0, 996.3, 998.6, 1026.66, 1009.555, 1016.777, 991.4, 991.0, 990.3, 989.8, 1036.7, 994.2, 989.3, 995.0, 1037.0, 1035.4, 993.9, 993.6, 984.2, 994.7, 997.3, 994.4, 992.8, 990.7, 1033.1, 987.4, 1036.9, 1035.8, 1037.8, 1033.9, 993.5, 993.3, 990.2, 993.2, 1037.3, 985.5, 1037.9, 996.6, 994.1, 991.9, 992.6, 985.0, 994.6, 1037.5, 1037.7, 990.9, 988.7, 992.5, 989.9, 987.3, 992.0, 990.4, 988.6, 992.7, 992.3, 987.1, 991.8, 991.1, 988.8, 991.5, 992.9, 991.7, 989.4, 992.4, 992.1, 1035.3, 988.2, 990.8, 990.6, 988.3, 987.7, 982.6, 986.5, 991.3, 1036.6, 1037.1, 985.6, 992.2, 987.8, 986.0, 1036.5, 985.2, 986.4, 986.6, 988.9, 984.9, 1038.0, 1038.2, 986.9, 989.6, 989.7, 989.2, 986.1, 985.1, 984.0, 985.3, 981.2, 988.4, 1037.2, 1037.6, 987.6, 980.2, 986.2, 987.0, 1038.5, 1038.9, 988.1, 990.1, 988.5, 990.0, 984.5, 987.2, 985.4, 981.4, 984.4, 989.1, 991.2, 982.2, 988.0, 977.1, 978.2, 983.2, 981.9, 983.3, 990.5, 1039.6, 986.8, 1038.4, 985.8, 989.5] Valores únicos de la columna Pressure9am -> [1007.7, 1010.6, 1007.6, 1017.6, 1010.8, 1009.2, 1009.6, 1013.4, 1008.9, 1007.0, 1011.8, 1010.5, 994.3, 1001.2, 1012.2, 1005.8, 1009.4, 1019.2, 1019.3, 1013.6, 1007.8, 1011.0, 1012.9, 1010.9, 1006.8, 1005.2, 1004.8, 1005.6, 1006.1, 1004.5, 1014.4, 1018.7, 1015.1, 1012.6, 1011.9, 1017.8, 1009.9, 1014.1, 1015.7, 1011.6, 1008.4, 1019.7, 1015.8, 1010.1, 1005.3, 1007.9, 1005.4, 1016.5, 1017.7, 1014.9, 1014.6, 1014.2, 1012.5, 1011.7, 1008.8, 1005.9, 1008.0, 1008.2, 1009.3, 1012.8, 1017.0, 1023.3, 1022.5, 1016.2, 1017.2, 1012.4, 1015.6, 1013.0, 1014.0, 1016.6, 1007.5, 1014.7, 1014.5, 1013.7, 1015.2, 1019.5, 1021.3, 1017.4, 1012.7, 1013.3, 1016.3, 1014.8, 1019.1, 1023.0, 1023.8, 1022.4, 1023.2, 1022.6, 1018.8, 1019.8, 1020.4, 1021.8, 1026.7, 1027.1, 1024.2, 1021.5, 1024.4, 1024.1, 1018.5, 1022.8, 1022.7, 1023.6, 1025.2, 1026.0, 1004.0, 1013.8, 1018.0, 1023.1, 1023.4, 1026.9, 1028.7, 1029.8, 1031.4, 1028.5, 1026.2, 1028.8, 1025.1, 1025.6, 1022.3, 1018.4, 1015.3, 1015.0, 1024.7, 1022.2, 1025.0, 1024.6, 1021.4, 1021.7, 1030.3, 1034.1, 1031.9, 1029.3, 1023.5, 1021.0, 1017.9, 1011.1, 1025.7, 1018.3, 1013.9, 1029.7, 1031.6, 1030.8, 1021.9, 1020.7, 1020.2, 1015.5, 1011.4, 1006.5, 1008.6, 1019.9, 1030.4, 1032.0, 1020.5, 1010.4, 1006.6, 1021.6, 1009.5, 1027.3, 1026.8, 1024.0, 1025.8, 1027.9, 1026.4, 1018.6, 1009.0, 1011.5, 1021.1, 1021.2, 1018.2, 1027.7, 1012.0, 1004.1, 1016.1, 1016.9, 1002.6, 1018.9, 1024.9, 1005.0, 1020.0, 997.8, 1009.8, 1012.3, 1020.6, 1029.5, 1001.9, 1000.5, 1008.5, 1016.0, 1026.6, 1022.9, 1020.8, 1019.6, 1027.5, 1025.4, 1017.1, 1029.1, 1010.0, 1003.7, 1010.7, 1010.3, 1022.0, 1015.9, 1006.9, 1019.4, 1018.1, 1013.5, 1016.8, 1017.5, 1015.4, 1006.7, 1013.2, 1016.4, 1017.3, 1020.3, 1023.9, 1016.7, 1008.7, 1036.3, 1035.2, 1030.0, 1025.5, 1022.1, 1026.5, 1027.8, 1020.9, 1023.7, 1005.7, 1004.7, 1031.8, 1032.3, 1027.4, 1027.2, 1034.5, 1037.3, 1036.9, 1030.1, 1024.3, 1027.6, 1030.5, 1032.5, 1030.9, 1029.2, 1032.7, 1035.5, 1032.1, 1031.7, 1035.9, 1036.1, 1024.5, 1006.2, 1003.1, 1029.6, 1028.9, 1024.8, 1026.1, 1026.3, 1028.2, 1028.4, 1025.3, 1029.4, 989.8, 1004.6, 1011.3, 1014.3, 1012.1, 1009.1, 1002.4, 998.8, 1002.3, 1006.0, 1009.7, 1004.4, 1007.4, 1002.5, 1019.0, 1020.1, 1001.4, 1031.5, 1033.0, 1002.9, 1025.9, 1028.0, 1027.0, 1002.0, 1028.3, 1031.0, 1035.7, 1037.4, 1038.9, 1033.6, 1036.6, 1031.3, 1010.2, 1039.9, 1013.1, 996.3, 1032.4, 1033.4, 1011.2, 1004.3, 1007.2, 1006.3, 995.3, 1000.9, 1005.5, 1030.2, 1035.1, 1033.8, 1036.5, 1034.4, 1003.3, 1031.1, 1031.2, 1029.0, 1028.6, 1033.1, 1033.2, 1007.3, 1000.8, 999.9, 1007.1, 1028.1, 1033.7, 1030.7, 1033.3, 1008.1, 1002.2, 1003.0, 1006.4, 1008.3, 998.9, 1000.7, 998.4, 1033.5, 1004.9, 1003.2, 1034.0, 1035.6, 1035.0, 1032.2, 1032.6, 1000.4, 1029.9, 1037.8, 1034.3, 1034.7, 1035.3, 1036.0, 1003.9, 1032.8, 1004.2, 1002.8, 996.0, 1003.4, 1037.5, 1038.2, 1034.8, 1000.1, 1032.9, 1033.9, 1003.6, 993.7, 992.9, 1000.3, 1001.3, 999.4, 1005.1, 996.6, 1036.8, 1030.6, 997.6, 1001.7, 1001.0, nan, 1036.2, 1035.4, 1037.6, 1038.0, 1003.5, 1001.5, 1038.6, 997.4, 1034.2, 1003.8, 997.3, 999.3, 996.8, 1037.0, 1034.9, 1039.2, 998.5, 998.6, 991.7, 1001.1, 1002.1, 1035.8, 1002.7, 998.3, 999.7, 999.0, 1037.1, 1001.6, 996.5, 997.2, 999.6, 1038.3, 1038.4, 1000.6, 999.2, 980.5, 1000.2, 994.9, 999.8, 1001.8, 994.6, 1037.9, 1038.7, 998.0, 999.1, 997.0, 1034.6, 1038.8, 1039.1, 990.2, 986.7, 995.0, 1036.7, 996.7, 999.5, 1039.0, 998.1, 1038.1, 997.7, 991.5, 1039.6, 998.7, 1000.0, 1037.7, 994.5, 994.8, 994.0, 996.1, 994.7, 997.1, 1037.2, 1036.4, 998.2, 987.4, 993.9, 996.9, 1039.3, 1039.5, 995.2, 1040.1, 1040.2, 1040.6, 996.4, 1040.3, 995.7, 995.4, 992.8, 996.2, 994.2, 1039.4, 995.9, 995.8, 997.9, 990.5, 993.3, 989.4, 992.0, 995.1, 992.5, 989.5, 991.2, 991.4, 992.1, 997.5, 993.0, 992.7, 989.3, 991.6, 993.8, 993.4, 995.5, 989.7, 993.6, 988.9, 992.4, 991.8, 993.5, 994.1, 991.3, 1038.5, 986.9, 990.3, 995.6, 993.2, 990.9, 994.4, 990.8, 991.1, 992.6, 986.2, 982.3, 989.6, 985.1, 982.0, 989.2, 1040.9, 992.3, 1041.0, 1040.4, 989.0, 988.3, 986.3, 988.0, 984.6, 992.2, 987.2, 982.9, 988.5, 989.1, 988.8, 987.0, 993.1, 1040.0, 991.9, 983.7, 985.8, 985.9, 987.3, 991.0, 987.1, 990.4, 986.6, 988.1, 988.2, 989.9, 982.2, 984.4, 983.9, 985.0, 1040.5, 1039.7, 987.9, 990.6]
Recomendaciones:
- Las columnas con menos de 10%, teniendo el contexto del caso, lo mejor sería utilizar KNNImputer o DecisionTree debido a la relevancia que tendrá cada variable pero debido al bajo porcentaje podría decidirse imputar por la moda o promedio.
- También se recomienda castear las columnas RainToday, WindDir3pm, WindGustDir y WindDir9am con One-Hot Encoding
3.3 Análisis de columnas con menos de 10% de valores nulos¶
- Lo primero que haremos es revisar los valores únicos para descartar que los valores nulos representen algo en cada columna y entender los posibles valores
columns_of_interest10 = ['Cloud9am','Cloud3pm','Evaporation','Sunshine']
for column in columns_of_interest10:
unique_values = df[column].unique().tolist()
print(f"Valores únicos de la columna {column} -> {unique_values}")
Valores únicos de la columna Cloud9am -> [8.0, nan, 7.0, 1.0, 0.0, 5.0, 4.0, 2.0, 6.0, 3.0, 9.0] Valores únicos de la columna Cloud3pm -> [nan, 2.0, 8.0, 7.0, 1.0, 5.0, 4.0, 6.0, 3.0, 0.0, 9.0] Valores únicos de la columna Evaporation -> [nan, 12.0, 14.8, 12.6, 10.8, 11.4, 11.2, 13.0, 9.8, 14.6, 11.0, 12.8, 13.8, 16.4, 17.4, 16.0, 13.6, 8.0, 8.2, 8.6, 14.2, 15.8, 16.2, 13.4, 14.4, 11.8, 15.6, 15.2, 11.6, 9.6, 6.6, 0.6, 6.0, 3.0, 2.0, 5.2, 9.0, 10.2, 10.0, 7.4, 8.4, 9.2, 9.4, 12.4, 10.4, 7.2, 6.8, 7.6, 4.4, 6.4, 7.8, 7.0, 8.8, 6.2, 5.8, 0.2, 2.4, 1.8, 2.2, 2.8, 5.0, 5.6, 4.8, 4.2, 4.0, 3.2, 4.6, 3.4, 3.6, 0.0, 1.4, 3.8, 0.8, 2.6, 1.6, 1.2, 1.0, 5.4, 10.6, 16.8, 17.0, 20.2, 14.0, 17.2, 12.2, 15.0, 18.2, 13.2, 4.1, 1.7, 0.4, 1.9, 64.8, 32.0, 26.2, 24.6, 23.3, 15.4, 32.6, 30.4, 34.4, 18.0, 49.4, 18.8, 19.0, 18.4, 8.1, 4.9, 25.2, 24.0, 22.4, 16.6, 48.8, 56.2, 37.0, 52.4, 17.6, 6.3, 20.0, 21.4, 25.0, 17.8, 25.6, 18.6, 21.6, 35.4, 23.0, 22.0, 30.8, 11.1, 19.8, 33.2, 86.2, 65.8, 56.4, 31.2, 21.8, 5.7, 2.7, 1.3, 2.5, 3.3, 9.9, 2.3, 0.7, 2.1, 1.1, 2.9, 1.5, 3.1, 6.1, 19.6, 9.7, 10.5, 5.9, 9.3, 20.4, 12.1, 30.6, 24.2, 0.3, 47.2, 19.2, 38.4, 34.6, 23.6, 44.2, 32.2, 31.4, 34.2, 20.6, 26.8, 22.6, 23.8, 38.6, 26.4, 46.8, 42.4, 46.6, 60.2, 37.6, 36.4, 48.4, 43.6, 35.0, 50.4, 35.8, 54.0, 41.2, 32.8, 35.6, 31.0, 32.4, 19.4, 60.8, 27.4, 43.4, 27.0, 36.8, 25.4, 57.2, 28.6, 33.6, 37.4, 23.4, 43.0, 36.2, 31.6, 39.2, 25.8, 65.4, 40.4, 26.0, 21.2, 7.1, 74.8, 37.2, 28.8, 5.3, 4.7, 8.7, 3.9, 3.5, 9.5, 0.9, 30.2, 14.7, 13.1, 7.5, 8.3, 5.1, 3.7, 5.5, 18.1, 4.3, 21.0, 33.8, 4.5, 20.5, 11.9, 6.9, 7.7, 9.1, 10.9, 19.7, 10.1, 6.7, 0.5, 13.9, 12.5, 0.1, 14.5, 19.1, 17.1, 7.3, 25.1, 22.2, 27.2, 19.3, 6.5, 27.6, 11.5, 22.8, 28.4, 20.8, 39.4, 27.8, 28.2, 26.6, 33.0, 29.8, 23.2, 33.4, 28.0, 38.0, 40.0, 29.2, 29.4, 38.8, 64.4, 30.0, 24.4, 24.8, 55.4, 59.2, 145.0, 47.0, 8.9, 13.5, 8.5, 11.3, 44.0, 7.9, 44.4, 22.1, 36.6, 36.0, 34.0, 14.9, 42.6, 14.3, 10.3, 11.7, 10.7, 81.2, 63.0, 70.0, 54.8, 59.8, 72.2, 64.0, 59.6, 59.0, 42.3, 12.7, 17.7, 22.5, 15.3, 35.2, 34.5, 23.1, 42.2, 82.4, 42.0, 43.2, 62.0, 77.3, 13.3, 55.2, 58.0, 57.6, 55.6, 46.2, 55.0, 50.8, 51.0, 68.8, 51.6, 58.5, 55.8, 53.6, 25.5, 56.0, 48.0, 70.4, 59.4, 56.6, 14.1, 12.3, 15.1, 16.5, 41.8, 40.8, 50.2, 41.6, 42.8, 39.6] Valores únicos de la columna Sunshine -> [nan, 12.3, 13.0, 13.3, 10.6, 12.2, 8.4, 0.0, 12.6, 13.2, 12.7, 12.1, 10.3, 13.1, 12.9, 11.3, 6.9, 10.9, 3.7, 5.9, 10.5, 12.4, 13.4, 13.6, 7.4, 10.0, 2.3, 6.6, 0.3, 10.7, 11.6, 10.2, 9.0, 12.0, 3.0, 7.9, 11.5, 11.2, 4.8, 5.8, 6.0, 11.1, 11.8, 11.4, 10.8, 7.8, 11.0, 5.5, 4.7, 4.2, 4.4, 6.2, 9.8, 9.9, 4.3, 8.0, 9.6, 10.4, 9.3, 8.7, 7.6, 7.5, 10.1, 6.3, 2.8, 0.7, 9.4, 9.7, 0.6, 5.1, 8.3, 4.1, 3.9, 6.8, 8.6, 2.7, 8.2, 3.1, 1.8, 0.1, 0.8, 3.4, 7.1, 5.0, 5.7, 6.1, 7.0, 2.9, 2.5, 4.6, 8.9, 9.1, 1.7, 8.1, 9.5, 1.2, 1.4, 8.8, 2.2, 3.5, 9.2, 1.9, 11.7, 11.9, 7.7, 0.9, 12.5, 2.1, 12.8, 13.7, 8.5, 0.2, 4.0, 2.4, 5.2, 0.5, 6.4, 4.5, 1.1, 2.0, 0.4, 1.5, 3.3, 6.5, 2.6, 3.8, 3.6, 3.2, 6.7, 5.4, 7.2, 4.9, 1.0, 1.6, 5.3, 7.3, 5.6, 1.3, 13.8, 13.5, 14.0, 13.9, 14.1, 14.5, 14.3, 14.2]
Recomendación: Las columnas con más de 10%, teniendo el contexto del caso, se recomienda utilizar KNNImputer o DecisionTree debido descartando por completo imputar por la moda o promedio. Esto debido a la relevancia que tendrá cada variable y más aún teniendo en cuenta el alto porcentaje de valores nulos que puede alcanzar hasta un 47%.
4 Revisión de Outliers¶
df.describe()
columnas_relevantes = ['MinTemp','MaxTemp','Rainfall',
'Evaporation','Sunshine','WindGustSpeed','WindSpeed9am','WindSpeed3pm','Humidity9am',
'Humidity3pm','Pressure9am','Pressure3pm','Cloud9am','Cloud3pm','Temp9am','Temp3pm','RISK_MM'] # Asegúrate de ajustar esto según tus necesidades
df_business_understanding = df[columnas_relevantes]
# Crear un gráfico de caja para cada variable numérica por separado
for columna in df_business_understanding.columns:
plt.figure(figsize=(8, 4)) # Ajusta el tamaño del gráfico según necesites
sns.boxplot(x=df_business_understanding[columna], palette="Set2")
plt.title(f'Diagrama de Caja para {columna}')
plt.xlabel('Valores')
plt.show()
for columna in df_business_understanding.columns:
q1 = df_business_understanding[columna].quantile(0.25)
q3 = df_business_understanding[columna].quantile(0.75)
iqr = q3 - q1
limite_inferior = q1 - 1.5 * iqr
limite_superior = q3 + 1.5 * iqr
# Contar outliers
outliers = df_business_understanding[columna][(df_business_understanding[columna] < limite_inferior) | (df_business_understanding[columna] > limite_superior)]
cantidad_outliers = outliers.count()
porcentaje_outliers = (cantidad_outliers / df_business_understanding.shape[0]) * 100
# Imprimir resultados
print(f"La cantidad de outliers en la variable {columna} es: {cantidad_outliers}")
print(f"El porcentaje de outliers en la variable {columna} es: {round(porcentaje_outliers, 2)}%")
print("\n")
La cantidad de outliers en la variable MinTemp es: 62 El porcentaje de outliers en la variable MinTemp es: 0.04% La cantidad de outliers en la variable MaxTemp es: 459 El porcentaje de outliers en la variable MaxTemp es: 0.32% La cantidad de outliers en la variable Rainfall es: 25228 El porcentaje de outliers en la variable Rainfall es: 17.74% La cantidad de outliers en la variable Evaporation es: 1954 El porcentaje de outliers en la variable Evaporation es: 1.37% La cantidad de outliers en la variable Sunshine es: 0 El porcentaje de outliers en la variable Sunshine es: 0.0% La cantidad de outliers en la variable WindGustSpeed es: 3006 El porcentaje de outliers en la variable WindGustSpeed es: 2.11% La cantidad de outliers en la variable WindSpeed9am es: 1739 El porcentaje de outliers en la variable WindSpeed9am es: 1.22% La cantidad de outliers en la variable WindSpeed3pm es: 2458 El porcentaje de outliers en la variable WindSpeed3pm es: 1.73% La cantidad de outliers en la variable Humidity9am es: 1419 El porcentaje de outliers en la variable Humidity9am es: 1.0% La cantidad de outliers en la variable Humidity3pm es: 0 El porcentaje de outliers en la variable Humidity3pm es: 0.0% La cantidad de outliers en la variable Pressure9am es: 1174 El porcentaje de outliers en la variable Pressure9am es: 0.83% La cantidad de outliers en la variable Pressure3pm es: 906 El porcentaje de outliers en la variable Pressure3pm es: 0.64% La cantidad de outliers en la variable Cloud9am es: 0 El porcentaje de outliers en la variable Cloud9am es: 0.0% La cantidad de outliers en la variable Cloud3pm es: 0 El porcentaje de outliers en la variable Cloud3pm es: 0.0% La cantidad de outliers en la variable Temp9am es: 247 El porcentaje de outliers en la variable Temp9am es: 0.17% La cantidad de outliers en la variable Temp3pm es: 735 El porcentaje de outliers en la variable Temp3pm es: 0.52% La cantidad de outliers en la variable RISK_MM es: 25573 El porcentaje de outliers en la variable RISK_MM es: 17.98%
Recomendaciones:
- Para las columnas Rainfall, RISK_MM, WindGustSpeed, WindSpeed9am, WindSpeed3pm: Dejar los datos atípicos, ya que serán importantes para predecir los futuros target preseleccionados.
- Evaporation, Humidity9am, Humidity3pm, Pressure9am y Pressure3pm: Se recomienda aplicar transformaciones para normalizar su distribución y reducir el impacto de valores extremadamente altos en el análisis.
- Para el resto de campos al ser menos al 1% podemos mantenerlos y considerar trabajarlos solo si es necesario mejorar para el modelado.
5 Distribución de datos para variables objetivo¶
5.1 RainTomorrow¶
rain_tomorrow_counts = df['RainTomorrow'].value_counts()
print(rain_tomorrow_counts)
RainTomorrow No 110316 Yes 31877 Name: count, dtype: int64
rain_tomorrow_percentages = df['RainTomorrow'].value_counts(normalize=True) * 100
print("Porcentaje de registros según 'RainTomorrow':")
print(rain_tomorrow_percentages)
Porcentaje de registros según 'RainTomorrow': RainTomorrow No 77.581878 Yes 22.418122 Name: proportion, dtype: float64
Recomendación: Utilizar técnicas de sobremuestreo para generar registros y así equilibrar la distribución
5.2 RISK_MM¶
plt.figure(figsize=(10, 6))
plt.hist(df['RISK_MM'], bins=50, edgecolor='k', alpha=0.7)
plt.title('Distribución de RISK_MM')
plt.xlabel('RISK_MM')
plt.ylabel('Frecuencia')
plt.grid(True)
plt.show()
# Boxplot
plt.figure(figsize=(10, 6))
sns.boxplot(x=df['RISK_MM'])
plt.title('Boxplot de RISK_MM')
plt.xlabel('RISK_MM')
plt.show()
# Estadísticas descriptivas
risk_mm_stats = df['RISK_MM'].describe()
print("Estadísticas descriptivas de RISK_MM:")
print(risk_mm_stats)
Estadísticas descriptivas de RISK_MM: count 142193.000000 mean 2.360682 std 8.477969 min 0.000000 25% 0.000000 50% 0.000000 75% 0.800000 max 371.000000 Name: RISK_MM, dtype: float64
# Configurar el tamaño del gráfico
plt.figure(figsize=(14, 8))
# Crear un gráfico de caja para RISK_MM por Location
ax = sns.boxplot(x='Location', y='RISK_MM', data=df)
# Configurar el título y las etiquetas de los ejes
plt.title('Distribución de RISK_MM por Ubicación con Línea en 90 mm')
plt.xlabel('Ubicación')
plt.ylabel('RISK_MM')
# Rotar las etiquetas del eje x para una mejor legibilidad
plt.xticks(rotation=90)
# Añadir línea horizontal en 90 mm de RISK_MM
plt.axhline(y=90, color='purple', linestyle='-', linewidth=2, label='Línea en 90 mm')
# Añadir leyenda para la línea en 90 mm
plt.legend()
# Mostrar el gráfico
plt.show()
count_risk_mm_high = (df['RISK_MM'] > 250).sum()
print(f"Cantidad de registros con RISK_MM > 250: {count_risk_mm_high}")
Cantidad de registros con RISK_MM > 250: 4
Análisis: Las regiones con mayor pick de RISK_MM coinciden con las regiones en las que normalmente llueve mas de acuerdo a las condiciones meteorológicas comunes de Australia y a su geografía. Esto se determinó teniendo en cuenta una linea que señala los 90mm, siendo esta la medida de riesgo máxima a la hora de preedcir la precipitación.
Recomendación: Se recomienda eliminar los registros con mas de 250 mm ya que pueden representar un riesgo en el sesgo de nuestras predicciones.
Fase 3: Data Preparation¶
Transformación, eliminación e imputación de datos¶
1. Unificación de datos nulos¶
Debido a que es probable que hayan datos nulos escritos de diferentes maneras, dejaremos todos los datos como np.nan
na_values = ('np.nan','NA','NaN','nan','inf','NULL')
df = df.replace(na_values, np.nan)
2. Imputación promedio para columnas con menos del 10% de valores nulos¶
Se imputara usando el promedio o moda según sea el caso
# Columnas a imputar
numeric_columns = ['MaxTemp', 'MinTemp', 'Temp9am', 'WindSpeed9am', 'WindGustSpeed', 'Rainfall',
'Humidity9am', 'WindSpeed3pm', 'Temp3pm', 'Humidity3pm',
'Pressure3pm', 'Pressure9am']
categorical_columns = ['RainToday', 'WindDir3pm', 'WindGustDir', 'WindDir9am']
# Imputación para columnas numéricas
numeric_imputer = SimpleImputer(strategy='mean')
df[numeric_columns] = numeric_imputer.fit_transform(df[numeric_columns])
# Imputación para columnas categóricas
categorical_imputer = SimpleImputer(strategy='most_frequent')
df[categorical_columns] = categorical_imputer.fit_transform(df[categorical_columns])
# Verificar la imputación
print(df.isnull().sum())
Date 0 Location 0 MinTemp 0 MaxTemp 0 Rainfall 0 Evaporation 60843 Sunshine 67816 WindGustDir 0 WindGustSpeed 0 WindDir9am 0 WindDir3pm 0 WindSpeed9am 0 WindSpeed3pm 0 Humidity9am 0 Humidity3pm 0 Pressure9am 0 Pressure3pm 0 Cloud9am 53657 Cloud3pm 57094 Temp9am 0 Temp3pm 0 RainToday 0 RISK_MM 0 RainTomorrow 0 dtype: int64
3. Imputación de columnas con valores nulos mayores al 10% por KNNImputer¶
# Columnas a imputar con KNNImputer
knn_columns = ['Evaporation', 'Sunshine', 'Cloud9am', 'Cloud3pm']
# Crear una copia del DataFrame para evitar la imputación en columnas no necesarias
df_knn = df[knn_columns].copy()
# KNN Imputer
knn_imputer = KNNImputer(n_neighbors=5)
# Realizar la imputación
df_knn_imputed = knn_imputer.fit_transform(df_knn)
# Convertir el resultado de nuevo a DataFrame y asignar los nombres de las columnas
df_knn_imputed = pd.DataFrame(df_knn_imputed, columns=knn_columns)
# Reemplazar las columnas originales con las columnas imputadas
df[knn_columns] = df_knn_imputed
# Verificar la imputación
print(df.isnull().sum())
Date 0 Location 0 MinTemp 0 MaxTemp 0 Rainfall 0 Evaporation 0 Sunshine 0 WindGustDir 0 WindGustSpeed 0 WindDir9am 0 WindDir3pm 0 WindSpeed9am 0 WindSpeed3pm 0 Humidity9am 0 Humidity3pm 0 Pressure9am 0 Pressure3pm 0 Cloud9am 0 Cloud3pm 0 Temp9am 0 Temp3pm 0 RainToday 0 RISK_MM 0 RainTomorrow 0 dtype: int64
Revisión de columnas con datos nulos
null_counts = df.isnull().sum()
null_counts[null_counts > 0].sort_values(ascending=False)
Series([], dtype: int64)
4. Eliminación de registros con mas de 250 en RISK_MM¶
# Eliminar los registros donde RISK_MM > 250
df = df[df['RISK_MM'] <= 250]
# Verificamos el tamaño del DataFrame original y el filtrado
print(f"Tamaño original del DataFrame: {df.shape[0]}")
print(f"Tamaño del DataFrame después de eliminar RISK_MM > 250: {df.shape[0]}")
Tamaño original del DataFrame: 142189 Tamaño del DataFrame después de eliminar RISK_MM > 250: 142189
5. Eliminación de la columna Date¶
# df = df.drop(columns=['Date'])
# Convertir la columna 'Date' a datetime
df['Date'] = pd.to_datetime(df['Date'])
# Extraer solo el mes y reemplazar la columna 'Date' con el mes
df['Date'] = df['Date'].dt.month
# Imprimir el DataFrame resultante
print(df)
Date Location MinTemp MaxTemp Rainfall Evaporation Sunshine \
0 12 Albury 13.4 22.9 0.6 4.560000 2.840000
1 12 Albury 7.4 25.1 0.0 5.469824 7.624853
2 12 Albury 12.9 25.7 0.0 4.440000 8.480000
3 12 Albury 9.2 28.0 0.0 5.469824 7.624853
4 12 Albury 17.5 32.3 1.0 5.880000 2.300000
... ... ... ... ... ... ... ...
142188 6 Uluru 3.5 21.8 0.0 5.469824 7.624853
142189 6 Uluru 2.8 23.4 0.0 5.469824 7.624853
142190 6 Uluru 3.6 25.3 0.0 5.469824 7.624853
142191 6 Uluru 5.4 26.9 0.0 5.469824 7.624853
142192 6 Uluru 7.8 27.0 0.0 6.840000 9.240000
WindGustDir WindGustSpeed WindDir9am ... Humidity3pm Pressure9am \
0 W 44.0 W ... 22.0 1007.7
1 WNW 44.0 NNW ... 25.0 1010.6
2 WSW 46.0 W ... 30.0 1007.6
3 NE 24.0 SE ... 16.0 1017.6
4 W 41.0 ENE ... 33.0 1010.8
... ... ... ... ... ... ...
142188 E 31.0 ESE ... 27.0 1024.7
142189 E 31.0 SE ... 24.0 1024.6
142190 NNW 22.0 SE ... 21.0 1023.5
142191 N 37.0 SE ... 24.0 1021.0
142192 SE 28.0 SSE ... 24.0 1019.4
Pressure3pm Cloud9am Cloud3pm Temp9am Temp3pm RainToday RISK_MM \
0 1007.1 8.000000 5.600000 16.9 21.8 No 0.0
1 1007.8 4.437189 4.503167 17.2 24.3 No 0.0
2 1008.7 4.600000 2.000000 21.0 23.2 No 0.0
3 1012.8 4.437189 4.503167 18.1 26.5 No 1.0
4 1006.0 7.000000 8.000000 17.8 29.7 No 0.2
... ... ... ... ... ... ... ...
142188 1021.2 4.437189 4.503167 9.4 20.9 No 0.0
142189 1020.3 4.437189 4.503167 10.1 22.4 No 0.0
142190 1019.1 4.437189 4.503167 10.9 24.5 No 0.0
142191 1016.8 4.437189 4.503167 12.5 26.1 No 0.0
142192 1016.5 3.000000 2.000000 15.1 26.0 No 0.0
RainTomorrow
0 No
1 No
2 No
3 No
4 No
... ...
142188 No
142189 No
142190 No
142191 No
142192 No
[142189 rows x 24 columns]
6.1 Transformación de location a regiones basado en un estudio del clima para la ganadería¶
# Diccionario de ubicaciones y climas
ubicaciones_climas = {
"Albury": "mediterraneo",
"BadgerysCreek": "mediterraneo",
"Cobar": "arido_calido",
"CoffsHarbour": "mediterraneo",
"Moree": "mediterraneo",
"Newcastle": "mediterraneo",
"NorahHead": "mediterraneo",
"NorfolkIsland": "mediterraneo",
"Penrith": "mediterraneo",
"Richmond": "mediterraneo",
"Sydney": "mediterraneo",
"SydneyAirport": "mediterraneo",
"WaggaWagga": "semiarido_calido",
"Williamtown": "mediterraneo",
"Wollongong": "mediterraneo",
"Canberra": "mediterraneo",
"Tuggeranong": "mediterraneo",
"MountGinini": "mediterraneo",
"Ballarat": "mediterraneo",
"Bendigo": "mediterraneo",
"Sale": "mediterraneo",
"MelbourneAirport": "mediterraneo",
"Melbourne": "mediterraneo",
"Mildura": "semiarido_calido",
"Nhil": "semiarido_calido",
"Portland": "mediterraneo",
"Watsonia": "mediterraneo",
"Dartmoor": "mediterraneo",
"Brisbane": "tropical_humedo",
"Cairns": "Sabana",
"GoldCoast": "tropical_humedo",
"Townsville": "Sabana",
"Adelaide": "mediterraneo",
"MountGambier": "mediterraneo",
"Nuriootpa": "mediterraneo",
"Woomera": "arido_calido",
"Albany": "mediterraneo",
"Witchcliffe": "mediterraneo",
"PearceRAAF": "mediterraneo",
"PerthAirport": "mediterraneo",
"Perth": "mediterraneo",
"SalmonGums": "mediterraneo",
"Walpole": "mediterraneo",
"Hobart": "mediterraneo",
"Launceston": "mediterraneo",
"AliceSprings": "arido_calido",
"Darwin": "Sabana",
"Katherine": "Sabana",
"Uluru": "arido_calido"
}
# Reemplazar los valores de la columna 'ubicacion' según el diccionario
df['Location'] = df['Location'].replace(ubicaciones_climas)
# Imprimir el DataFrame resultante
print(df)
Date Location MinTemp MaxTemp Rainfall Evaporation Sunshine \
0 12 mediterraneo 13.4 22.9 0.6 4.560000 2.840000
1 12 mediterraneo 7.4 25.1 0.0 5.469824 7.624853
2 12 mediterraneo 12.9 25.7 0.0 4.440000 8.480000
3 12 mediterraneo 9.2 28.0 0.0 5.469824 7.624853
4 12 mediterraneo 17.5 32.3 1.0 5.880000 2.300000
... ... ... ... ... ... ... ...
142188 6 arido_calido 3.5 21.8 0.0 5.469824 7.624853
142189 6 arido_calido 2.8 23.4 0.0 5.469824 7.624853
142190 6 arido_calido 3.6 25.3 0.0 5.469824 7.624853
142191 6 arido_calido 5.4 26.9 0.0 5.469824 7.624853
142192 6 arido_calido 7.8 27.0 0.0 6.840000 9.240000
WindGustDir WindGustSpeed WindDir9am ... Humidity3pm Pressure9am \
0 W 44.0 W ... 22.0 1007.7
1 WNW 44.0 NNW ... 25.0 1010.6
2 WSW 46.0 W ... 30.0 1007.6
3 NE 24.0 SE ... 16.0 1017.6
4 W 41.0 ENE ... 33.0 1010.8
... ... ... ... ... ... ...
142188 E 31.0 ESE ... 27.0 1024.7
142189 E 31.0 SE ... 24.0 1024.6
142190 NNW 22.0 SE ... 21.0 1023.5
142191 N 37.0 SE ... 24.0 1021.0
142192 SE 28.0 SSE ... 24.0 1019.4
Pressure3pm Cloud9am Cloud3pm Temp9am Temp3pm RainToday RISK_MM \
0 1007.1 8.000000 5.600000 16.9 21.8 No 0.0
1 1007.8 4.437189 4.503167 17.2 24.3 No 0.0
2 1008.7 4.600000 2.000000 21.0 23.2 No 0.0
3 1012.8 4.437189 4.503167 18.1 26.5 No 1.0
4 1006.0 7.000000 8.000000 17.8 29.7 No 0.2
... ... ... ... ... ... ... ...
142188 1021.2 4.437189 4.503167 9.4 20.9 No 0.0
142189 1020.3 4.437189 4.503167 10.1 22.4 No 0.0
142190 1019.1 4.437189 4.503167 10.9 24.5 No 0.0
142191 1016.8 4.437189 4.503167 12.5 26.1 No 0.0
142192 1016.5 3.000000 2.000000 15.1 26.0 No 0.0
RainTomorrow
0 No
1 No
2 No
3 No
4 No
... ...
142188 No
142189 No
142190 No
142191 No
142192 No
[142189 rows x 24 columns]
6. One Hot Encoding¶
categorical_columns = ['Location','WindGustDir','WindDir9am','WindDir3pm','RainToday','RainTomorrow']
# Inicializar el OneHotEncoder
encoder = OneHotEncoder(sparse=False, handle_unknown='ignore')
# Aplicar el encoder y transformar las columnas categóricas
encoded_columns = encoder.fit_transform(df[categorical_columns])
# Crear un DataFrame con las columnas codificadas
encoded_df = pd.DataFrame(encoded_columns, columns=encoder.get_feature_names_out(categorical_columns))
# Concatenar las columnas codificadas con el DataFrame original (excluyendo las columnas originales)
df = pd.concat([df.drop(columns=categorical_columns), encoded_df], axis=1)
# Verificar la transformación
print(df.head())
c:\Python311\Lib\site-packages\sklearn\preprocessing\_encoders.py:868: FutureWarning: `sparse` was renamed to `sparse_output` in version 1.2 and will be removed in 1.4. `sparse_output` is ignored unless you leave `sparse` to its default value. warnings.warn(
Date MinTemp MaxTemp Rainfall Evaporation Sunshine WindGustSpeed \ 0 12.0 13.4 22.9 0.6 4.560000 2.840000 44.0 1 12.0 7.4 25.1 0.0 5.469824 7.624853 44.0 2 12.0 12.9 25.7 0.0 4.440000 8.480000 46.0 3 12.0 9.2 28.0 0.0 5.469824 7.624853 24.0 4 12.0 17.5 32.3 1.0 5.880000 2.300000 41.0 WindSpeed9am WindSpeed3pm Humidity9am ... WindDir3pm_SSE \ 0 20.0 24.0 71.0 ... 0.0 1 4.0 22.0 44.0 ... 0.0 2 19.0 26.0 38.0 ... 0.0 3 11.0 9.0 45.0 ... 0.0 4 7.0 20.0 82.0 ... 0.0 WindDir3pm_SSW WindDir3pm_SW WindDir3pm_W WindDir3pm_WNW \ 0 0.0 0.0 0.0 1.0 1 0.0 0.0 0.0 0.0 2 0.0 0.0 0.0 0.0 3 0.0 0.0 0.0 0.0 4 0.0 0.0 0.0 0.0 WindDir3pm_WSW RainToday_No RainToday_Yes RainTomorrow_No \ 0 0.0 1.0 0.0 1.0 1 1.0 1.0 0.0 1.0 2 1.0 1.0 0.0 1.0 3 0.0 1.0 0.0 1.0 4 0.0 1.0 0.0 1.0 RainTomorrow_Yes 0 0.0 1 0.0 2 0.0 3 0.0 4 0.0 [5 rows x 75 columns]
df.info(max_cols=300)
<class 'pandas.core.frame.DataFrame'> Index: 142193 entries, 0 to 136880 Data columns (total 75 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 142189 non-null float64 1 MinTemp 142189 non-null float64 2 MaxTemp 142189 non-null float64 3 Rainfall 142189 non-null float64 4 Evaporation 142189 non-null float64 5 Sunshine 142189 non-null float64 6 WindGustSpeed 142189 non-null float64 7 WindSpeed9am 142189 non-null float64 8 WindSpeed3pm 142189 non-null float64 9 Humidity9am 142189 non-null float64 10 Humidity3pm 142189 non-null float64 11 Pressure9am 142189 non-null float64 12 Pressure3pm 142189 non-null float64 13 Cloud9am 142189 non-null float64 14 Cloud3pm 142189 non-null float64 15 Temp9am 142189 non-null float64 16 Temp3pm 142189 non-null float64 17 RISK_MM 142189 non-null float64 18 Location_Sabana 142189 non-null float64 19 Location_arido_calido 142189 non-null float64 20 Location_mediterraneo 142189 non-null float64 21 Location_semiarido_calido 142189 non-null float64 22 Location_tropical_humedo 142189 non-null float64 23 WindGustDir_E 142189 non-null float64 24 WindGustDir_ENE 142189 non-null float64 25 WindGustDir_ESE 142189 non-null float64 26 WindGustDir_N 142189 non-null float64 27 WindGustDir_NE 142189 non-null float64 28 WindGustDir_NNE 142189 non-null float64 29 WindGustDir_NNW 142189 non-null float64 30 WindGustDir_NW 142189 non-null float64 31 WindGustDir_S 142189 non-null float64 32 WindGustDir_SE 142189 non-null float64 33 WindGustDir_SSE 142189 non-null float64 34 WindGustDir_SSW 142189 non-null float64 35 WindGustDir_SW 142189 non-null float64 36 WindGustDir_W 142189 non-null float64 37 WindGustDir_WNW 142189 non-null float64 38 WindGustDir_WSW 142189 non-null float64 39 WindDir9am_E 142189 non-null float64 40 WindDir9am_ENE 142189 non-null float64 41 WindDir9am_ESE 142189 non-null float64 42 WindDir9am_N 142189 non-null float64 43 WindDir9am_NE 142189 non-null float64 44 WindDir9am_NNE 142189 non-null float64 45 WindDir9am_NNW 142189 non-null float64 46 WindDir9am_NW 142189 non-null float64 47 WindDir9am_S 142189 non-null float64 48 WindDir9am_SE 142189 non-null float64 49 WindDir9am_SSE 142189 non-null float64 50 WindDir9am_SSW 142189 non-null float64 51 WindDir9am_SW 142189 non-null float64 52 WindDir9am_W 142189 non-null float64 53 WindDir9am_WNW 142189 non-null float64 54 WindDir9am_WSW 142189 non-null float64 55 WindDir3pm_E 142189 non-null float64 56 WindDir3pm_ENE 142189 non-null float64 57 WindDir3pm_ESE 142189 non-null float64 58 WindDir3pm_N 142189 non-null float64 59 WindDir3pm_NE 142189 non-null float64 60 WindDir3pm_NNE 142189 non-null float64 61 WindDir3pm_NNW 142189 non-null float64 62 WindDir3pm_NW 142189 non-null float64 63 WindDir3pm_S 142189 non-null float64 64 WindDir3pm_SE 142189 non-null float64 65 WindDir3pm_SSE 142189 non-null float64 66 WindDir3pm_SSW 142189 non-null float64 67 WindDir3pm_SW 142189 non-null float64 68 WindDir3pm_W 142189 non-null float64 69 WindDir3pm_WNW 142189 non-null float64 70 WindDir3pm_WSW 142189 non-null float64 71 RainToday_No 142189 non-null float64 72 RainToday_Yes 142189 non-null float64 73 RainTomorrow_No 142189 non-null float64 74 RainTomorrow_Yes 142189 non-null float64 dtypes: float64(75) memory usage: 82.4 MB
Nos quedaremos solo con RainTomorrow_1 para la futura predicción
df = df.drop(columns=['RainTomorrow_No'])
print(df.isnull().sum())
Date 4
MinTemp 4
MaxTemp 4
Rainfall 4
Evaporation 4
..
WindDir3pm_WNW 4
WindDir3pm_WSW 4
RainToday_No 4
RainToday_Yes 4
RainTomorrow_Yes 4
Length: 74, dtype: int64
print(f"Cantidad de registros antes de eliminar nulos: {len(df)}")
# Eliminar registros con al menos un campo nulo
df.dropna(inplace=True)
# Mostrar la cantidad de registros después de eliminar los nulos
print(f"Cantidad de registros después de eliminar nulos: {len(df)}")
Cantidad de registros antes de eliminar nulos: 142193 Cantidad de registros después de eliminar nulos: 142185 Cantidad de registros después de eliminar nulos: 142185
7. Generación de registros para balancear RainTomorrow¶
# Definir las características (X) y la variable objetivo (y)
X = df.drop(columns=['RainTomorrow_Yes'])
y = df['RainTomorrow_Yes']
# Crear el objeto SMOTE
smote = SMOTE(random_state=42)
# Aplicar SMOTE
X_resampled, y_resampled = smote.fit_resample(X, y)
# Crear un nuevo DataFrame con los datos sobremuestreados
df_resampled = pd.DataFrame(X_resampled, columns=X.columns)
df_resampled['RainTomorrow_Yes'] = y_resampled
# Mostrar información sobre el nuevo DataFrame
print(df_resampled.info())
<class 'pandas.core.frame.DataFrame'> RangeIndex: 220630 entries, 0 to 220629 Data columns (total 74 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 220630 non-null float64 1 MinTemp 220630 non-null float64 2 MaxTemp 220630 non-null float64 3 Rainfall 220630 non-null float64 4 Evaporation 220630 non-null float64 5 Sunshine 220630 non-null float64 6 WindGustSpeed 220630 non-null float64 7 WindSpeed9am 220630 non-null float64 8 WindSpeed3pm 220630 non-null float64 9 Humidity9am 220630 non-null float64 10 Humidity3pm 220630 non-null float64 11 Pressure9am 220630 non-null float64 12 Pressure3pm 220630 non-null float64 13 Cloud9am 220630 non-null float64 14 Cloud3pm 220630 non-null float64 15 Temp9am 220630 non-null float64 16 Temp3pm 220630 non-null float64 17 RISK_MM 220630 non-null float64 18 Location_Sabana 220630 non-null float64 19 Location_arido_calido 220630 non-null float64 20 Location_mediterraneo 220630 non-null float64 21 Location_semiarido_calido 220630 non-null float64 22 Location_tropical_humedo 220630 non-null float64 23 WindGustDir_E 220630 non-null float64 24 WindGustDir_ENE 220630 non-null float64 25 WindGustDir_ESE 220630 non-null float64 26 WindGustDir_N 220630 non-null float64 27 WindGustDir_NE 220630 non-null float64 28 WindGustDir_NNE 220630 non-null float64 29 WindGustDir_NNW 220630 non-null float64 30 WindGustDir_NW 220630 non-null float64 31 WindGustDir_S 220630 non-null float64 32 WindGustDir_SE 220630 non-null float64 33 WindGustDir_SSE 220630 non-null float64 34 WindGustDir_SSW 220630 non-null float64 35 WindGustDir_SW 220630 non-null float64 36 WindGustDir_W 220630 non-null float64 37 WindGustDir_WNW 220630 non-null float64 38 WindGustDir_WSW 220630 non-null float64 39 WindDir9am_E 220630 non-null float64 40 WindDir9am_ENE 220630 non-null float64 41 WindDir9am_ESE 220630 non-null float64 42 WindDir9am_N 220630 non-null float64 43 WindDir9am_NE 220630 non-null float64 44 WindDir9am_NNE 220630 non-null float64 45 WindDir9am_NNW 220630 non-null float64 46 WindDir9am_NW 220630 non-null float64 47 WindDir9am_S 220630 non-null float64 48 WindDir9am_SE 220630 non-null float64 49 WindDir9am_SSE 220630 non-null float64 50 WindDir9am_SSW 220630 non-null float64 51 WindDir9am_SW 220630 non-null float64 52 WindDir9am_W 220630 non-null float64 53 WindDir9am_WNW 220630 non-null float64 54 WindDir9am_WSW 220630 non-null float64 55 WindDir3pm_E 220630 non-null float64 56 WindDir3pm_ENE 220630 non-null float64 57 WindDir3pm_ESE 220630 non-null float64 58 WindDir3pm_N 220630 non-null float64 59 WindDir3pm_NE 220630 non-null float64 60 WindDir3pm_NNE 220630 non-null float64 61 WindDir3pm_NNW 220630 non-null float64 62 WindDir3pm_NW 220630 non-null float64 63 WindDir3pm_S 220630 non-null float64 64 WindDir3pm_SE 220630 non-null float64 65 WindDir3pm_SSE 220630 non-null float64 66 WindDir3pm_SSW 220630 non-null float64 67 WindDir3pm_SW 220630 non-null float64 68 WindDir3pm_W 220630 non-null float64 69 WindDir3pm_WNW 220630 non-null float64 70 WindDir3pm_WSW 220630 non-null float64 71 RainToday_No 220630 non-null float64 72 RainToday_Yes 220630 non-null float64 73 RainTomorrow_Yes 220630 non-null float64 dtypes: float64(74) memory usage: 124.6 MB None
df_resampled.info(max_cols=200)
<class 'pandas.core.frame.DataFrame'> RangeIndex: 220630 entries, 0 to 220629 Data columns (total 74 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 220630 non-null float64 1 MinTemp 220630 non-null float64 2 MaxTemp 220630 non-null float64 3 Rainfall 220630 non-null float64 4 Evaporation 220630 non-null float64 5 Sunshine 220630 non-null float64 6 WindGustSpeed 220630 non-null float64 7 WindSpeed9am 220630 non-null float64 8 WindSpeed3pm 220630 non-null float64 9 Humidity9am 220630 non-null float64 10 Humidity3pm 220630 non-null float64 11 Pressure9am 220630 non-null float64 12 Pressure3pm 220630 non-null float64 13 Cloud9am 220630 non-null float64 14 Cloud3pm 220630 non-null float64 15 Temp9am 220630 non-null float64 16 Temp3pm 220630 non-null float64 17 RISK_MM 220630 non-null float64 18 Location_Sabana 220630 non-null float64 19 Location_arido_calido 220630 non-null float64 20 Location_mediterraneo 220630 non-null float64 21 Location_semiarido_calido 220630 non-null float64 22 Location_tropical_humedo 220630 non-null float64 23 WindGustDir_E 220630 non-null float64 24 WindGustDir_ENE 220630 non-null float64 25 WindGustDir_ESE 220630 non-null float64 26 WindGustDir_N 220630 non-null float64 27 WindGustDir_NE 220630 non-null float64 28 WindGustDir_NNE 220630 non-null float64 29 WindGustDir_NNW 220630 non-null float64 30 WindGustDir_NW 220630 non-null float64 31 WindGustDir_S 220630 non-null float64 32 WindGustDir_SE 220630 non-null float64 33 WindGustDir_SSE 220630 non-null float64 34 WindGustDir_SSW 220630 non-null float64 35 WindGustDir_SW 220630 non-null float64 36 WindGustDir_W 220630 non-null float64 37 WindGustDir_WNW 220630 non-null float64 38 WindGustDir_WSW 220630 non-null float64 39 WindDir9am_E 220630 non-null float64 40 WindDir9am_ENE 220630 non-null float64 41 WindDir9am_ESE 220630 non-null float64 42 WindDir9am_N 220630 non-null float64 43 WindDir9am_NE 220630 non-null float64 44 WindDir9am_NNE 220630 non-null float64 45 WindDir9am_NNW 220630 non-null float64 46 WindDir9am_NW 220630 non-null float64 47 WindDir9am_S 220630 non-null float64 48 WindDir9am_SE 220630 non-null float64 49 WindDir9am_SSE 220630 non-null float64 50 WindDir9am_SSW 220630 non-null float64 51 WindDir9am_SW 220630 non-null float64 52 WindDir9am_W 220630 non-null float64 53 WindDir9am_WNW 220630 non-null float64 54 WindDir9am_WSW 220630 non-null float64 55 WindDir3pm_E 220630 non-null float64 56 WindDir3pm_ENE 220630 non-null float64 57 WindDir3pm_ESE 220630 non-null float64 58 WindDir3pm_N 220630 non-null float64 59 WindDir3pm_NE 220630 non-null float64 60 WindDir3pm_NNE 220630 non-null float64 61 WindDir3pm_NNW 220630 non-null float64 62 WindDir3pm_NW 220630 non-null float64 63 WindDir3pm_S 220630 non-null float64 64 WindDir3pm_SE 220630 non-null float64 65 WindDir3pm_SSE 220630 non-null float64 66 WindDir3pm_SSW 220630 non-null float64 67 WindDir3pm_SW 220630 non-null float64 68 WindDir3pm_W 220630 non-null float64 69 WindDir3pm_WNW 220630 non-null float64 70 WindDir3pm_WSW 220630 non-null float64 71 RainToday_No 220630 non-null float64 72 RainToday_Yes 220630 non-null float64 73 RainTomorrow_Yes 220630 non-null float64 dtypes: float64(74) memory usage: 124.6 MB
rain_tomorrow_counts = df_resampled['RainTomorrow_Yes'].value_counts()
print(rain_tomorrow_counts)
RainTomorrow_Yes 0.0 110315 1.0 110315 Name: count, dtype: int64
rain_tomorrow_percentages = df_resampled['RainTomorrow_Yes'].value_counts(normalize=True) * 100
print("Porcentaje de registros según 'RainTomorrow_Yes':")
print(rain_tomorrow_percentages)
Porcentaje de registros según 'RainTomorrow_Yes': RainTomorrow_Yes 0.0 50.0 1.0 50.0 Name: proportion, dtype: float64
4. Manejo de Outliers¶
4.1 Realizamos tranformaciones en las columna Evaporation, Humidity9am, Humidity3pm, Pressure9am y Pressure3pm¶
df_resampled['Evaporation'] = df_resampled['Evaporation'].apply(lambda x: np.log(x + 1)) # +1 para manejar
df_resampled['Humidity9am'] = df_resampled['Humidity9am'].apply(lambda x: np.log(x + 1))
df_resampled['Humidity3pm'] = df_resampled['Humidity3pm'].apply(lambda x: np.log(x + 1))
df_resampled['Pressure9am'] = df_resampled['Pressure9am'].apply(lambda x: np.log(x + 1))
df_resampled['Pressure3pm'] = df_resampled['Pressure3pm'].apply(lambda x: np.log(x + 1))
# Verifica los resultados tras la transformación
print(df_resampled[['Evaporation', 'Humidity9am', 'Humidity3pm', 'Pressure9am', 'Pressure3pm']].head())
Evaporation Humidity9am Humidity3pm Pressure9am Pressure3pm 0 1.715598 4.276666 3.135494 6.916418 6.915823 1 1.867149 3.806662 3.258097 6.919289 6.916517 2 1.693779 3.663562 3.433987 6.916319 6.917409 3 1.867149 3.828641 2.833213 6.926184 6.921461 4 1.928619 4.418841 3.526361 6.919486 6.914731
for columna in df_resampled.columns:
q1 = df_resampled[columna].quantile(0.25)
q3 = df_resampled[columna].quantile(0.75)
iqr = q3 - q1
limite_inferior = q1 - 1.5 * iqr
limite_superior = q3 + 1.5 * iqr
# Contar outliers
outliers = df_resampled[columna][(df_resampled[columna] < limite_inferior) | (df_resampled[columna] > limite_superior)]
cantidad_outliers = outliers.count()
porcentaje_outliers = (cantidad_outliers / df_resampled.shape[0]) * 100
# Imprimir resultados
print(f"La cantidad de outliers en la variable {columna} es: {cantidad_outliers}")
print(f"El porcentaje de outliers en la variable {columna} es: {round(porcentaje_outliers, 2)}%")
print("\n")
La cantidad de outliers en la variable Date es: 0 El porcentaje de outliers en la variable Date es: 0.0% La cantidad de outliers en la variable MinTemp es: 64 El porcentaje de outliers en la variable MinTemp es: 0.03% La cantidad de outliers en la variable MaxTemp es: 733 El porcentaje de outliers en la variable MaxTemp es: 0.33% La cantidad de outliers en la variable Rainfall es: 35712 El porcentaje de outliers en la variable Rainfall es: 16.19% La cantidad de outliers en la variable Evaporation es: 25361 El porcentaje de outliers en la variable Evaporation es: 11.49% La cantidad de outliers en la variable Sunshine es: 7206 El porcentaje de outliers en la variable Sunshine es: 3.27% La cantidad de outliers en la variable WindGustSpeed es: 6180 El porcentaje de outliers en la variable WindGustSpeed es: 2.8% La cantidad de outliers en la variable WindSpeed9am es: 2863 El porcentaje de outliers en la variable WindSpeed9am es: 1.3% La cantidad de outliers en la variable WindSpeed3pm es: 3836 El porcentaje de outliers en la variable WindSpeed3pm es: 1.74% La cantidad de outliers en la variable Humidity9am es: 8827 El porcentaje de outliers en la variable Humidity9am es: 4.0% La cantidad de outliers en la variable Humidity3pm es: 10441 El porcentaje de outliers en la variable Humidity3pm es: 4.73% La cantidad de outliers en la variable Pressure9am es: 3951 El porcentaje de outliers en la variable Pressure9am es: 1.79% La cantidad de outliers en la variable Pressure3pm es: 3310 El porcentaje de outliers en la variable Pressure3pm es: 1.5% La cantidad de outliers en la variable Cloud9am es: 0 El porcentaje de outliers en la variable Cloud9am es: 0.0% La cantidad de outliers en la variable Cloud3pm es: 5110 El porcentaje de outliers en la variable Cloud3pm es: 2.32% La cantidad de outliers en la variable Temp9am es: 353 El porcentaje de outliers en la variable Temp9am es: 0.16% La cantidad de outliers en la variable Temp3pm es: 1369 El porcentaje de outliers en la variable Temp3pm es: 0.62% La cantidad de outliers en la variable RISK_MM es: 35386 El porcentaje de outliers en la variable RISK_MM es: 16.04% La cantidad de outliers en la variable Location_Sabana es: 18856 El porcentaje de outliers en la variable Location_Sabana es: 8.55% La cantidad de outliers en la variable Location_arido_calido es: 14405 El porcentaje de outliers en la variable Location_arido_calido es: 6.53% La cantidad de outliers en la variable Location_mediterraneo es: 53879 El porcentaje de outliers en la variable Location_mediterraneo es: 24.42% La cantidad de outliers en la variable Location_semiarido_calido es: 12442 El porcentaje de outliers en la variable Location_semiarido_calido es: 5.64% La cantidad de outliers en la variable Location_tropical_humedo es: 11910 El porcentaje de outliers en la variable Location_tropical_humedo es: 5.4% La cantidad de outliers en la variable WindGustDir_E es: 15346 El porcentaje de outliers en la variable WindGustDir_E es: 6.96% La cantidad de outliers en la variable WindGustDir_ENE es: 14061 El porcentaje de outliers en la variable WindGustDir_ENE es: 6.37% La cantidad de outliers en la variable WindGustDir_ESE es: 12869 El porcentaje de outliers en la variable WindGustDir_ESE es: 5.83% La cantidad de outliers en la variable WindGustDir_N es: 20210 El porcentaje de outliers en la variable WindGustDir_N es: 9.16% La cantidad de outliers en la variable WindGustDir_NE es: 13274 El porcentaje de outliers en la variable WindGustDir_NE es: 6.02% La cantidad de outliers en la variable WindGustDir_NNE es: 13652 El porcentaje de outliers en la variable WindGustDir_NNE es: 6.19% La cantidad de outliers en la variable WindGustDir_NNW es: 15503 El porcentaje de outliers en la variable WindGustDir_NNW es: 7.03% La cantidad de outliers en la variable WindGustDir_NW es: 18886 El porcentaje de outliers en la variable WindGustDir_NW es: 8.56% La cantidad de outliers en la variable WindGustDir_S es: 18192 El porcentaje de outliers en la variable WindGustDir_S es: 8.25% La cantidad de outliers en la variable WindGustDir_SE es: 17433 El porcentaje de outliers en la variable WindGustDir_SE es: 7.9% La cantidad de outliers en la variable WindGustDir_SSE es: 17186 El porcentaje de outliers en la variable WindGustDir_SSE es: 7.79% La cantidad de outliers en la variable WindGustDir_SSW es: 17406 El porcentaje de outliers en la variable WindGustDir_SSW es: 7.89% La cantidad de outliers en la variable WindGustDir_SW es: 17160 El porcentaje de outliers en la variable WindGustDir_SW es: 7.78% La cantidad de outliers en la variable WindGustDir_W es: 39912 El porcentaje de outliers en la variable WindGustDir_W es: 18.09% La cantidad de outliers en la variable WindGustDir_WNW es: 18641 El porcentaje de outliers en la variable WindGustDir_WNW es: 8.45% La cantidad de outliers en la variable WindGustDir_WSW es: 18731 El porcentaje de outliers en la variable WindGustDir_WSW es: 8.49% La cantidad de outliers en la variable WindDir9am_E es: 14937 El porcentaje de outliers en la variable WindDir9am_E es: 6.77% La cantidad de outliers en la variable WindDir9am_ENE es: 14192 El porcentaje de outliers en la variable WindDir9am_ENE es: 6.43% La cantidad de outliers en la variable WindDir9am_ESE es: 12662 El porcentaje de outliers en la variable WindDir9am_ESE es: 5.74% La cantidad de outliers en la variable WindDir9am_N es: 44940 El porcentaje de outliers en la variable WindDir9am_N es: 20.37% La cantidad de outliers en la variable WindDir9am_NE es: 14908 El porcentaje de outliers en la variable WindDir9am_NE es: 6.76% La cantidad de outliers en la variable WindDir9am_NNE es: 18076 El porcentaje de outliers en la variable WindDir9am_NNE es: 8.19% La cantidad de outliers en la variable WindDir9am_NNW es: 19075 El porcentaje de outliers en la variable WindDir9am_NNW es: 8.65% La cantidad de outliers en la variable WindDir9am_NW es: 19945 El porcentaje de outliers en la variable WindDir9am_NW es: 9.04% La cantidad de outliers en la variable WindDir9am_S es: 16538 El porcentaje de outliers en la variable WindDir9am_S es: 7.5% La cantidad de outliers en la variable WindDir9am_SE es: 16146 El porcentaje de outliers en la variable WindDir9am_SE es: 7.32% La cantidad de outliers en la variable WindDir9am_SSE es: 16304 El porcentaje de outliers en la variable WindDir9am_SSE es: 7.39% La cantidad de outliers en la variable WindDir9am_SSW es: 15262 El porcentaje de outliers en la variable WindDir9am_SSW es: 6.92% La cantidad de outliers en la variable WindDir9am_SW es: 17131 El porcentaje de outliers en la variable WindDir9am_SW es: 7.76% La cantidad de outliers en la variable WindDir9am_W es: 18173 El porcentaje de outliers en la variable WindDir9am_W es: 8.24% La cantidad de outliers en la variable WindDir9am_WNW es: 16502 El porcentaje de outliers en la variable WindDir9am_WNW es: 7.48% La cantidad de outliers en la variable WindDir9am_WSW es: 14765 El porcentaje de outliers en la variable WindDir9am_WSW es: 6.69% La cantidad de outliers en la variable WindDir3pm_E es: 14984 El porcentaje de outliers en la variable WindDir3pm_E es: 6.79% La cantidad de outliers en la variable WindDir3pm_ENE es: 14243 El porcentaje de outliers en la variable WindDir3pm_ENE es: 6.46% La cantidad de outliers en la variable WindDir3pm_ESE es: 14937 El porcentaje de outliers en la variable WindDir3pm_ESE es: 6.77% La cantidad de outliers en la variable WindDir3pm_N es: 19677 El porcentaje de outliers en la variable WindDir3pm_N es: 8.92% La cantidad de outliers en la variable WindDir3pm_NE es: 15486 El porcentaje de outliers en la variable WindDir3pm_NE es: 7.02% La cantidad de outliers en la variable WindDir3pm_NNE es: 13890 El porcentaje de outliers en la variable WindDir3pm_NNE es: 6.3% La cantidad de outliers en la variable WindDir3pm_NNW es: 17740 El porcentaje de outliers en la variable WindDir3pm_NNW es: 8.04% La cantidad de outliers en la variable WindDir3pm_NW es: 19972 El porcentaje de outliers en la variable WindDir3pm_NW es: 9.05% La cantidad de outliers en la variable WindDir3pm_S es: 19146 El porcentaje de outliers en la variable WindDir3pm_S es: 8.68% La cantidad de outliers en la variable WindDir3pm_SE es: 27923 El porcentaje de outliers en la variable WindDir3pm_SE es: 12.66% La cantidad de outliers en la variable WindDir3pm_SSE es: 17359 El porcentaje de outliers en la variable WindDir3pm_SSE es: 7.87% La cantidad de outliers en la variable WindDir3pm_SSW es: 16280 El porcentaje de outliers en la variable WindDir3pm_SSW es: 7.38% La cantidad de outliers en la variable WindDir3pm_SW es: 17701 El porcentaje de outliers en la variable WindDir3pm_SW es: 8.02% La cantidad de outliers en la variable WindDir3pm_W es: 21530 El porcentaje de outliers en la variable WindDir3pm_W es: 9.76% La cantidad de outliers en la variable WindDir3pm_WNW es: 19964 El porcentaje de outliers en la variable WindDir3pm_WNW es: 9.05% La cantidad de outliers en la variable WindDir3pm_WSW es: 19106 El porcentaje de outliers en la variable WindDir3pm_WSW es: 8.66% La cantidad de outliers en la variable RainToday_No es: 0 El porcentaje de outliers en la variable RainToday_No es: 0.0% La cantidad de outliers en la variable RainToday_Yes es: 0 El porcentaje de outliers en la variable RainToday_Yes es: 0.0% La cantidad de outliers en la variable RainTomorrow_Yes es: 0 El porcentaje de outliers en la variable RainTomorrow_Yes es: 0.0%
5. Revisión final luego de Data Preparation¶
6.1 Cantidad de nulos¶
print(f'Cantidad total de nulos -> {df.isna().sum().sum()}')
Cantidad total de nulos -> 0
6.2 Outliers finales¶
df.describe()
columnas_relevantes = ['MinTemp','MaxTemp','Rainfall',
'Evaporation','Sunshine','WindGustSpeed','WindSpeed9am','WindSpeed3pm','Humidity9am',
'Humidity3pm','Pressure9am','Pressure3pm','Cloud9am','Cloud3pm','Temp9am','Temp3pm','RISK_MM'] # Asegúrate de ajustar esto según tus necesidades
df_business_understanding = df[columnas_relevantes]
# Crear un gráfico de caja para cada variable numérica por separado
for columna in df_business_understanding.columns:
plt.figure(figsize=(8, 4)) # Ajusta el tamaño del gráfico según necesites
sns.boxplot(x=df_business_understanding[columna], palette="Set2")
plt.title(f'Diagrama de Caja para {columna}')
plt.xlabel('Valores')
plt.show()
7. DataSet Limpio¶
df.head()
| Date | MinTemp | MaxTemp | Rainfall | Evaporation | Sunshine | WindGustSpeed | WindSpeed9am | WindSpeed3pm | Humidity9am | ... | WindDir3pm_SE | WindDir3pm_SSE | WindDir3pm_SSW | WindDir3pm_SW | WindDir3pm_W | WindDir3pm_WNW | WindDir3pm_WSW | RainToday_No | RainToday_Yes | RainTomorrow_Yes | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 12.0 | 13.4 | 22.9 | 0.6 | 4.560000 | 2.840000 | 44.0 | 20.0 | 24.0 | 71.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 |
| 1 | 12.0 | 7.4 | 25.1 | 0.0 | 5.469824 | 7.624853 | 44.0 | 4.0 | 22.0 | 44.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 |
| 2 | 12.0 | 12.9 | 25.7 | 0.0 | 4.440000 | 8.480000 | 46.0 | 19.0 | 26.0 | 38.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 1.0 | 0.0 | 0.0 |
| 3 | 12.0 | 9.2 | 28.0 | 0.0 | 5.469824 | 7.624853 | 24.0 | 11.0 | 9.0 | 45.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
| 4 | 12.0 | 17.5 | 32.3 | 1.0 | 5.880000 | 2.300000 | 41.0 | 7.0 | 20.0 | 82.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 1.0 | 0.0 | 0.0 |
5 rows × 74 columns
df.info(max_cols=200)
<class 'pandas.core.frame.DataFrame'> Index: 142185 entries, 0 to 142188 Data columns (total 74 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Date 142185 non-null float64 1 MinTemp 142185 non-null float64 2 MaxTemp 142185 non-null float64 3 Rainfall 142185 non-null float64 4 Evaporation 142185 non-null float64 5 Sunshine 142185 non-null float64 6 WindGustSpeed 142185 non-null float64 7 WindSpeed9am 142185 non-null float64 8 WindSpeed3pm 142185 non-null float64 9 Humidity9am 142185 non-null float64 10 Humidity3pm 142185 non-null float64 11 Pressure9am 142185 non-null float64 12 Pressure3pm 142185 non-null float64 13 Cloud9am 142185 non-null float64 14 Cloud3pm 142185 non-null float64 15 Temp9am 142185 non-null float64 16 Temp3pm 142185 non-null float64 17 RISK_MM 142185 non-null float64 18 Location_Sabana 142185 non-null float64 19 Location_arido_calido 142185 non-null float64 20 Location_mediterraneo 142185 non-null float64 21 Location_semiarido_calido 142185 non-null float64 22 Location_tropical_humedo 142185 non-null float64 23 WindGustDir_E 142185 non-null float64 24 WindGustDir_ENE 142185 non-null float64 25 WindGustDir_ESE 142185 non-null float64 26 WindGustDir_N 142185 non-null float64 27 WindGustDir_NE 142185 non-null float64 28 WindGustDir_NNE 142185 non-null float64 29 WindGustDir_NNW 142185 non-null float64 30 WindGustDir_NW 142185 non-null float64 31 WindGustDir_S 142185 non-null float64 32 WindGustDir_SE 142185 non-null float64 33 WindGustDir_SSE 142185 non-null float64 34 WindGustDir_SSW 142185 non-null float64 35 WindGustDir_SW 142185 non-null float64 36 WindGustDir_W 142185 non-null float64 37 WindGustDir_WNW 142185 non-null float64 38 WindGustDir_WSW 142185 non-null float64 39 WindDir9am_E 142185 non-null float64 40 WindDir9am_ENE 142185 non-null float64 41 WindDir9am_ESE 142185 non-null float64 42 WindDir9am_N 142185 non-null float64 43 WindDir9am_NE 142185 non-null float64 44 WindDir9am_NNE 142185 non-null float64 45 WindDir9am_NNW 142185 non-null float64 46 WindDir9am_NW 142185 non-null float64 47 WindDir9am_S 142185 non-null float64 48 WindDir9am_SE 142185 non-null float64 49 WindDir9am_SSE 142185 non-null float64 50 WindDir9am_SSW 142185 non-null float64 51 WindDir9am_SW 142185 non-null float64 52 WindDir9am_W 142185 non-null float64 53 WindDir9am_WNW 142185 non-null float64 54 WindDir9am_WSW 142185 non-null float64 55 WindDir3pm_E 142185 non-null float64 56 WindDir3pm_ENE 142185 non-null float64 57 WindDir3pm_ESE 142185 non-null float64 58 WindDir3pm_N 142185 non-null float64 59 WindDir3pm_NE 142185 non-null float64 60 WindDir3pm_NNE 142185 non-null float64 61 WindDir3pm_NNW 142185 non-null float64 62 WindDir3pm_NW 142185 non-null float64 63 WindDir3pm_S 142185 non-null float64 64 WindDir3pm_SE 142185 non-null float64 65 WindDir3pm_SSE 142185 non-null float64 66 WindDir3pm_SSW 142185 non-null float64 67 WindDir3pm_SW 142185 non-null float64 68 WindDir3pm_W 142185 non-null float64 69 WindDir3pm_WNW 142185 non-null float64 70 WindDir3pm_WSW 142185 non-null float64 71 RainToday_No 142185 non-null float64 72 RainToday_Yes 142185 non-null float64 73 RainTomorrow_Yes 142185 non-null float64 dtypes: float64(74) memory usage: 81.4 MB
Fase 4: Modeling¶
Regresión¶
Para nuestra predicción hemos definido la variable objecto RISK_MM
df_regresionTotal = df_resampled[['MinTemp','MaxTemp','Rainfall','Evaporation','Sunshine','WindGustSpeed','WindSpeed9am','WindSpeed3pm',
'Humidity9am','Humidity3pm','Pressure9am','Pressure3pm','Cloud9am','Cloud3pm','Temp9am','Temp3pm','RISK_MM',
"Location_Sabana","Location_arido_calido","Location_mediterraneo","Location_semiarido_calido","Location_tropical_humedo",
'WindGustDir_E','WindGustDir_ENE','WindGustDir_ESE','WindGustDir_N',
'WindGustDir_NE','WindGustDir_NNE','WindGustDir_NNW','WindGustDir_NW','WindGustDir_S','WindGustDir_SE','WindGustDir_SSE',
'WindGustDir_SSW','WindGustDir_SW','WindGustDir_W','WindGustDir_WNW','WindGustDir_WSW','WindDir9am_E','WindDir9am_ENE',
'WindDir9am_ESE','WindDir9am_N','WindDir9am_NE','WindDir9am_NNE','WindDir9am_NNW','WindDir9am_NW','WindDir9am_S',
'WindDir9am_SE','WindDir9am_SSE','WindDir9am_SSW','WindDir9am_SW','WindDir9am_W','WindDir9am_WNW','WindDir9am_WSW',
'WindDir3pm_E','WindDir3pm_ENE','WindDir3pm_ESE','WindDir3pm_N','WindDir3pm_NE','WindDir3pm_NNE','WindDir3pm_NNW',
'WindDir3pm_NW','WindDir3pm_S','WindDir3pm_SE','WindDir3pm_SSE','WindDir3pm_SSW','WindDir3pm_SW','WindDir3pm_W',
'WindDir3pm_WNW','WindDir3pm_WSW','RainToday_No','RainToday_Yes','RainTomorrow_Yes', 'Date']]
corr = df_regresionTotal.corr()
sns.heatmap(corr, annot=True, linewidths=.9)
<Axes: >
Top 20 Correlación en RainTomorrow_Yes
# Calculamos la matriz de correlación
corr_matrix = df_resampled.corr()
# Usamos solo la parte superior de la matriz de correlación
upper_triangle = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(bool))
# Aplanamos la matriz y convertimos a un DataFrame para facilitar la manipulación
corr_unstacked = upper_triangle.unstack().reset_index()
corr_unstacked.columns = ['Variable1', 'Variable2', 'Correlation']
# Filtramos para conservar solo las filas que incluyen 'RainTomorrow_Yes'
corr_with_risk_mm = corr_unstacked[(corr_unstacked['Variable1'] == 'RainTomorrow_Yes') | (corr_unstacked['Variable2'] == 'RainTomorrow_Yes')]
# Ordenamos por el valor absoluto de la correlación, de mayor a menor
corr_with_risk_mm['AbsCorrelation'] = corr_with_risk_mm['Correlation'].abs()
top_correlations = corr_with_risk_mm.sort_values(by='AbsCorrelation', ascending=False)
# Seleccionamos las 20 correlaciones más fuertes
top_20_correlations = top_correlations.head(30)
# Imprimimos las 20 mejores correlaciones
print(top_20_correlations[['Variable1', 'Variable2', 'Correlation']])
Variable1 Variable2 Correlation 5474 RainTomorrow_Yes RainToday_Yes 0.347714 5473 RainTomorrow_Yes RainToday_No -0.347714 5412 RainTomorrow_Yes Humidity3pm 0.247677 5411 RainTomorrow_Yes Humidity9am 0.189232 5419 RainTomorrow_Yes RISK_MM 0.184053 5416 RainTomorrow_Yes Cloud3pm 0.181727 5407 RainTomorrow_Yes Sunshine -0.176238 5415 RainTomorrow_Yes Cloud9am 0.152351 5421 RainTomorrow_Yes Location_arido_calido -0.128704 5418 RainTomorrow_Yes Temp3pm -0.111842 5404 RainTomorrow_Yes MaxTemp -0.108034 5405 RainTomorrow_Yes Rainfall 0.102220 5406 RainTomorrow_Yes Evaporation -0.100966 5422 RainTomorrow_Yes Location_mediterraneo 0.085279 5414 RainTomorrow_Yes Pressure3pm -0.083013 5413 RainTomorrow_Yes Pressure9am -0.076489 5441 RainTomorrow_Yes WindDir9am_E -0.068848 5425 RainTomorrow_Yes WindGustDir_E -0.063393 5443 RainTomorrow_Yes WindDir9am_ESE -0.061130 5423 RainTomorrow_Yes Location_semiarido_calido -0.060909 5447 RainTomorrow_Yes WindDir9am_NNW 0.060078 5450 RainTomorrow_Yes WindDir9am_SE -0.051194 5408 RainTomorrow_Yes WindGustSpeed 0.049632 5426 RainTomorrow_Yes WindGustDir_ENE -0.048718 5438 RainTomorrow_Yes WindGustDir_W 0.047220 5464 RainTomorrow_Yes WindDir3pm_NW 0.046740 5432 RainTomorrow_Yes WindGustDir_NW 0.046519 5427 RainTomorrow_Yes WindGustDir_ESE -0.046049 5459 RainTomorrow_Yes WindDir3pm_ESE -0.045247 5448 RainTomorrow_Yes WindDir9am_NW 0.044698
C:\Users\nicol\AppData\Local\Temp\ipykernel_7508\489232418.py:15: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy corr_with_risk_mm['AbsCorrelation'] = corr_with_risk_mm['Correlation'].abs()
RainTomorrow_Yes:
'RainToday_Yes','Humidity3pm','Humidity9am','RISK_MM','Cloud3pm','Sunshine','Cloud9am','Temp3pm','MaxTemp','Rainfall','Evaporation','Pressure3pm','Pressure9am'
Top 20 Correlación en RISK_MM
# Calculamos la matriz de correlación
corr_matrix = df_resampled.corr()
# Usamos solo la parte superior de la matriz de correlación
upper_triangle = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(bool))
# Aplanamos la matriz y convertimos a un DataFrame para facilitar la manipulación
corr_unstacked = upper_triangle.unstack().reset_index()
corr_unstacked.columns = ['Variable1', 'Variable2', 'Correlation']
# Filtramos para conservar solo las filas que incluyen 'RISK_MM'
corr_with_risk_mm = corr_unstacked[(corr_unstacked['Variable1'] == 'RISK_MM') | (corr_unstacked['Variable2'] == 'RISK_MM')]
# Ordenamos por el valor absoluto de la correlación, de mayor a menor
corr_with_risk_mm['AbsCorrelation'] = corr_with_risk_mm['Correlation'].abs()
top_correlations_risk_mm = corr_with_risk_mm.sort_values(by='AbsCorrelation', ascending=False)
# Seleccionamos las 20 correlaciones más fuertes
top_20_correlations_risk_mm = top_correlations_risk_mm.head(30)
# Imprimimos las 20 mejores correlaciones
print(top_20_correlations_risk_mm[['Variable1', 'Variable2', 'Correlation']])
Variable1 Variable2 Correlation 5345 RainToday_Yes RISK_MM 0.365370 5271 RainToday_No RISK_MM -0.365370 1261 RISK_MM Rainfall 0.308477 1263 RISK_MM Sunshine -0.269812 1268 RISK_MM Humidity3pm 0.264688 1272 RISK_MM Cloud3pm 0.227069 1271 RISK_MM Cloud9am 0.195392 5419 RainTomorrow_Yes RISK_MM 0.184053 1267 RISK_MM Humidity9am 0.167888 1264 RISK_MM WindGustSpeed 0.163198 1269 RISK_MM Pressure9am -0.162409 1270 RISK_MM Pressure3pm -0.161860 1259 RISK_MM MinTemp 0.148224 1349 Location_Sabana RISK_MM 0.085550 1265 RISK_MM WindSpeed9am 0.076263 1273 RISK_MM Temp9am 0.067447 1274 RISK_MM Temp3pm -0.059104 1258 RISK_MM Date -0.056000 1423 Location_arido_calido RISK_MM -0.048795 1266 RISK_MM WindSpeed3pm 0.047342 3125 WindDir9am_N RISK_MM -0.040698 3791 WindDir9am_SW RISK_MM 0.038771 2311 WindGustDir_S RISK_MM 0.037951 1260 RISK_MM MaxTemp -0.036772 1571 Location_semiarido_calido RISK_MM -0.033903 3717 WindDir9am_SSW RISK_MM 0.032000 4901 WindDir3pm_SSW RISK_MM 0.031511 3273 WindDir9am_NNE RISK_MM -0.029205 3495 WindDir9am_S RISK_MM 0.028584 1941 WindGustDir_N RISK_MM -0.023572
C:\Users\nicol\AppData\Local\Temp\ipykernel_7508\1168011706.py:15: SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame. Try using .loc[row_indexer,col_indexer] = value instead See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy corr_with_risk_mm['AbsCorrelation'] = corr_with_risk_mm['Correlation'].abs()
RISK_MM:
'RainToday_Yes','Rainfall','Sunshine','Humidity3pm','Cloud3pm','Cloud9am','RainTomorrow_Yes','Humidity9am','WindGustSpeed','Pressure9am','Pressure3pm','MinTemp','WindSpeed9am','Temp9am','Temp3pm'
Se agregan la columna location y date¶
df_regresion = df_resampled[['RainToday_Yes','Rainfall','Sunshine','Humidity3pm','Cloud3pm','Cloud9am','RainTomorrow_Yes','Humidity9am','WindGustSpeed','Pressure9am','Pressure3pm','MinTemp','WindSpeed9am','Temp9am','Temp3pm',"Location_Sabana","Location_arido_calido","Location_mediterraneo","Location_semiarido_calido","Location_tropical_humedo", 'Date']]
corr = df_regresion.corr()
plt.figure(figsize=(12, 10))
sns.heatmap(corr, annot=True, linewidths=.9)
plt.show()
Target seleccionado : RainTomorrow_Yes¶
Separamos datos de entrenamiento y testeo¶
from sklearn.model_selection import train_test_split
# separar el dataframe en train y test con un 80% para train y 20% para test y random_state=42 y stratify=df['CUPO_L1']
X_train_reg, X_test_reg, y_train_reg, y_test_reg = train_test_split(df_regresion.drop(['RainTomorrow_Yes'], axis=1), df_regresion['RainTomorrow_Yes'], test_size=0.2, random_state=42)
Modelos sin hiperparámetros¶
Realizaremos un entrenamiento previo sin hiperparámetros para tener una vista preliminar del posible mejor modelo, los modelos seleccionados serán:
- DecisionTreeRegressor
- RandomForestRegressor
- GradientBoostingRegressor
- SVR
- KNeighborsRegressor
- SGDRegressor
# importar todos los modelos de regresion de sklearn
from sklearn.tree import DecisionTreeRegressor
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.neighbors import KNeighborsRegressor
from sklearn.linear_model import SGDRegressor
Modelos sin hiperparámetros¶
# inicializar los modelos de regresion con los parametros por defecto
dtR = DecisionTreeRegressor()
rfR = RandomForestRegressor()
gbR = GradientBoostingRegressor()
knnR = KNeighborsRegressor()
sgdR = SGDRegressor()
Entrenamiento de los modelos¶
# entrenar los modelos de regresion con los datos de train
dtR.fit(X_train_reg, y_train_reg)
rfR.fit(X_train_reg, y_train_reg)
gbR.fit(X_train_reg, y_train_reg)
knnR.fit(X_train_reg, y_train_reg)
sgdR.fit(X_train_reg, y_train_reg)
# generar una lista con todos los modelos de regresion
models = [dtR, rfR, gbR, knnR, sgdR]
Vista del R² y Raíz del error cuadrática medio¶
# for que recorra la lista de modelos y que imprima el MAE, MSE y RMSE, R2 de cada modelo
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
i = 1
for model in models:
y_pred_reg = model.predict(X_test_reg)
print(f'{i}° Modelo de Clasificación -> {model}\n')
print('-'*100)
print(f'El MSE del modelo es {mean_squared_error(y_test_reg, y_pred_reg):.3f}')
print(f'El RMSE del modelo es {np.sqrt(mean_squared_error(y_test_reg, y_pred_reg)):.3f}')
print(f'El R² del modelo es {r2_score(y_test_reg, y_pred_reg):.2f}\n')
print('-'*100,'\n')
i += 1
1° Modelo de Clasificación -> DecisionTreeRegressor() ---------------------------------------------------------------------------------------------------- El MSE del modelo es 0.205 El RMSE del modelo es 0.453 El R² del modelo es 0.18 ---------------------------------------------------------------------------------------------------- 2° Modelo de Clasificación -> RandomForestRegressor() ---------------------------------------------------------------------------------------------------- El MSE del modelo es 0.100 El RMSE del modelo es 0.316 El R² del modelo es 0.60 ---------------------------------------------------------------------------------------------------- 3° Modelo de Clasificación -> GradientBoostingRegressor() ---------------------------------------------------------------------------------------------------- El MSE del modelo es 0.136 El RMSE del modelo es 0.368 El R² del modelo es 0.46 ---------------------------------------------------------------------------------------------------- 4° Modelo de Clasificación -> KNeighborsRegressor() ---------------------------------------------------------------------------------------------------- El MSE del modelo es 0.195 El RMSE del modelo es 0.442 El R² del modelo es 0.22 ---------------------------------------------------------------------------------------------------- 5° Modelo de Clasificación -> SGDRegressor() ---------------------------------------------------------------------------------------------------- El MSE del modelo es 1052419330.356 El RMSE del modelo es 32441.013 El R² del modelo es -4209684593.47 ----------------------------------------------------------------------------------------------------
Entrenamiento de Modelos con hiperparámetros¶
GradientBoostingRegressor¶
GradientBoostingRegressor V1¶
gbV1 = GradientBoostingRegressor( learning_rate=0.1, n_estimators=100, max_depth=3, tol=2, random_state=42)
gbV1.fit(X_train_reg, y_train_reg)
GradientBoostingRegressor(random_state=42, tol=2)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(random_state=42, tol=2)
GradientBoostingRegressor V2¶
gbV2 = GradientBoostingRegressor(
learning_rate=0.1, n_estimators=500, max_depth=3, tol=2, random_state=42)
gbV2.fit(X_train_reg, y_train_reg)
GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2)
GradientBoostingRegressor V3¶
gbV3 = GradientBoostingRegressor(
learning_rate=0.1, n_estimators=100, max_depth=30, tol=2, random_state=42)
gbV3.fit(X_train_reg, y_train_reg)
GradientBoostingRegressor(max_depth=30, random_state=42, tol=2)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(max_depth=30, random_state=42, tol=2)
GradientBoostingRegressor V4¶
gbV4 = GradientBoostingRegressor(learning_rate=0.4, n_estimators=3, max_depth=300, tol=1e-2, random_state=42)
gbV4.fit(X_train_reg, y_train_reg)
GradientBoostingRegressor(learning_rate=0.4, max_depth=300, n_estimators=3,
random_state=42, tol=0.01)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(learning_rate=0.4, max_depth=300, n_estimators=3,
random_state=42, tol=0.01)GradientBoostingRegressor V5¶
gbV5 = GradientBoostingRegressor( learning_rate=0.4, n_estimators=1, max_depth=3000, tol=1e-2, random_state=42)
gbV5.fit(X_train_reg, y_train_reg)
GradientBoostingRegressor(learning_rate=0.4, max_depth=3000, n_estimators=1,
random_state=42, tol=0.01)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingRegressor(learning_rate=0.4, max_depth=3000, n_estimators=1,
random_state=42, tol=0.01)GradientBoostingRegressor V6¶
Revisión de R² y RMSE de las 6 versiones de GradientBoostingRegressor¶
models = [gbV1, gbV2, gbV3, gbV4, gbV5]
i = 1
for model in models:
y_pred_reg = model.predict(X_test_reg)
print(f'{i}° Modelo de Clasificación -> {model}\n')
print('-'*100)
print(
f'El MSE del modelo es {mean_squared_error(y_test_reg, y_pred_reg):.3f}')
print(f'El RMSE del modelo es {np.sqrt(mean_squared_error(y_test_reg, y_pred_reg)):.3f}')
print(f'El R² del modelo es {r2_score(y_test_reg, y_pred_reg):.2f}\n')
print('-'*100, '\n')
i += 1
1° Modelo de Clasificación -> GradientBoostingRegressor(random_state=42, tol=2)
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.136
El RMSE del modelo es 0.368
El R² del modelo es 0.46
----------------------------------------------------------------------------------------------------
2° Modelo de Clasificación -> GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2)
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.112
El RMSE del modelo es 0.335
El R² del modelo es 0.55
----------------------------------------------------------------------------------------------------
3° Modelo de Clasificación -> GradientBoostingRegressor(max_depth=30, random_state=42, tol=2)
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.147
El RMSE del modelo es 0.383
El R² del modelo es 0.41
----------------------------------------------------------------------------------------------------
4° Modelo de Clasificación -> GradientBoostingRegressor(learning_rate=0.4, max_depth=300, n_estimators=3,
random_state=42, tol=0.01)
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.161
El RMSE del modelo es 0.402
El R² del modelo es 0.35
----------------------------------------------------------------------------------------------------
5° Modelo de Clasificación -> GradientBoostingRegressor(learning_rate=0.4, max_depth=3000, n_estimators=1,
random_state=42, tol=0.01)
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.171
El RMSE del modelo es 0.414
El R² del modelo es 0.32
----------------------------------------------------------------------------------------------------
DecisionTreeRegressor¶
dtrV1 = DecisionTreeRegressor(
min_samples_split=5, min_samples_leaf=5, random_state=42)
dtrV1.fit(X_train_reg, y_train_reg)
DecisionTreeRegressor(min_samples_leaf=5, min_samples_split=5, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeRegressor(min_samples_leaf=5, min_samples_split=5, random_state=42)
RandomForestRegressor¶
RandomForestRegressor V1¶
rfRV1 = RandomForestRegressor(min_samples_split=5, min_samples_leaf=5, random_state=42,
bootstrap=True, max_samples=0.8, n_estimators=3, max_depth=40)
rfRV1.fit(X_train_reg, y_train_reg)
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=5,
min_samples_split=5, n_estimators=3, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=5,
min_samples_split=5, n_estimators=3, random_state=42)RandomForestRegressor V2¶
rfRV2 = RandomForestRegressor(min_samples_split=20, min_samples_leaf=20, random_state=42,
bootstrap=True, max_samples=0.8, n_estimators=12, max_depth=40)
rfRV2.fit(X_train_reg, y_train_reg)
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20,
min_samples_split=20, n_estimators=12, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20,
min_samples_split=20, n_estimators=12, random_state=42)KNeighborsRegressor¶
knnRV1 = KNeighborsRegressor(
n_neighbors=2000, weights='distance', algorithm='auto', leaf_size=40, p=2)
knnRV1.fit(X_train_reg, y_train_reg)
KNeighborsRegressor(leaf_size=40, n_neighbors=2000, weights='distance')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KNeighborsRegressor(leaf_size=40, n_neighbors=2000, weights='distance')
# generar una lista con todos los modelos de regresion
models = [dtrV1, rfRV1, rfRV2, knnRV1]
i=1
# for que recorra la lista de modelos y que imprima el RMSE, R2 de cada modelo
for model in models:
y_pred_reg = model.predict(X_test_reg)
print(f'{i}° Modelo de Clasificación -> {model}\n')
print('-'*100)
print(
f'El MSE del modelo es {mean_squared_error(y_test_reg, y_pred_reg):.3f}')
print(
f'El RMSE del modelo es $ {np.sqrt(mean_squared_error(y_test_reg, y_pred_reg)):.3f}')
print(f'El R² del modelo es {r2_score(y_test_reg, y_pred_reg):.2f}\n')
print('-'*100,'\n')
i = i + 1
1° Modelo de Clasificación -> DecisionTreeRegressor(min_samples_leaf=5, min_samples_split=5, random_state=42)
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.161
El RMSE del modelo es $ 0.401
El R² del modelo es 0.36
----------------------------------------------------------------------------------------------------
2° Modelo de Clasificación -> RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=5,
min_samples_split=5, n_estimators=3, random_state=42)
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.128
El RMSE del modelo es $ 0.358
El R² del modelo es 0.49
----------------------------------------------------------------------------------------------------
3° Modelo de Clasificación -> RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20,
min_samples_split=20, n_estimators=12, random_state=42)
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.114
El RMSE del modelo es $ 0.337
El R² del modelo es 0.55
----------------------------------------------------------------------------------------------------
4° Modelo de Clasificación -> KNeighborsRegressor(leaf_size=40, n_neighbors=2000, weights='distance')
----------------------------------------------------------------------------------------------------
El MSE del modelo es 0.230
El RMSE del modelo es $ 0.480
El R² del modelo es 0.08
----------------------------------------------------------------------------------------------------
Decisión¶
Los tres mejores modelos fueron los siguientes:
RandomForestRegressor() R²: 0.58 RandomForestRegressor ofrece el mejor rendimiento con un R² de 0.58. Su capacidad para manejar características no lineales y alta dimensionalidad lo hace ideal para datos complejos como los meteorológicos. Además, su naturaleza de ensemble ayuda a reducir el sobreajuste.
RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20, min_samples_split=20, n_estimators=12, random_state=42) R²: 0.52 Este modelo optimizado de RandomForestRegressor, aunque ligeramente inferior al anterior, sigue siendo robusto. Las especificaciones de profundidad máxima y tamaño de muestra ayudan a controlar el sobreajuste, proporcionando un buen equilibrio entre sesgo y varianza.
GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2) R²: 0.53 GradientBoostingRegressor con n_estimators ajustado a 500 ofrece un rendimiento cercano al mejor modelo de RandomForest. Su enfoque de boosting mejora iterativamente la precisión.
Teniendo en cuenta estos resultados el elegido será random fores sin hiper parametros
Para nuestra predicción hemos definido la variable objecto RainTomorrow_Yes, para ello nos apoyaremos en las siguientes variables
df_clas = df_resampled[['RainTomorrow_Yes','RainToday_Yes','Humidity3pm','Humidity9am','RISK_MM','Cloud3pm','Sunshine','Cloud9am','Temp3pm','MaxTemp','Rainfall','Evaporation','Pressure3pm','Pressure9am',"Location_Sabana","Location_arido_calido","Location_mediterraneo","Location_semiarido_calido","Location_tropical_humedo", 'Date']]
corr = df_clas.corr()
sns.heatmap(corr, annot=True, linewidths=.9)
<Axes: >
Importe de librerías
# importar todos los modelos de clasificacion de sklearn
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.neighbors import KNeighborsClassifier
Separamos datos de entrenamiento y testeo¶
# separar train y test de def_clas con un 80% para train y 20% para test y random_state=42
X_train_clas, X_test_clas, y_train_clas, y_test_clas = train_test_split(
df_clas.drop(['RainTomorrow_Yes'], axis=1), df_clas['RainTomorrow_Yes'], test_size=0.2, random_state=42)
Modelos sin hiperparámetros¶
Realizaremos un entrenamiento previo sin hiperparámetros para tener una vista preliminar del posible mejor modelo, los modelos seleccionados serán:
- DecisionTreeClassifier
- RandomForestClassifier
- GradientBoostingClassifier
- KNeighborsClassifier
dt = DecisionTreeClassifier()
dt.fit(X_train_clas, y_train_clas)
DecisionTreeClassifier()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier()
rf = RandomForestClassifier()
rf.fit(X_train_clas, y_train_clas)
RandomForestClassifier()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier()
gb = GradientBoostingClassifier()
gb.fit(X_train_clas, y_train_clas)
GradientBoostingClassifier()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingClassifier()
knn = KNeighborsClassifier()
knn.fit(X_train_clas, y_train_clas)
KNeighborsClassifier()In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KNeighborsClassifier()
Entrenamiento de Modelos con hiperparámetros¶
DecisionTreeClassifier¶
DecisionTreeClassifier V1¶
dt_1 = DecisionTreeClassifier(max_depth=2, random_state=42, criterion='entropy')
dt_1.fit(X_train_clas, y_train_clas)
DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)
DecisionTreeClassifier V2¶
dt_2 = DecisionTreeClassifier(
max_depth=2, random_state=42, criterion='gini')
dt_2.fit(X_train_clas, y_train_clas)
DecisionTreeClassifier(max_depth=2, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(max_depth=2, random_state=42)
DecisionTreeClassifier V3¶
dt_3 = DecisionTreeClassifier(
max_depth=2, random_state=42, criterion='log_loss')
dt_3.fit(X_train_clas, y_train_clas)
DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)
DecisionTreeClassifier V4¶
dt_4 = DecisionTreeClassifier(
max_depth=2, random_state=42, criterion='gini', min_samples_leaf=10)
dt_4.fit(X_train_clas, y_train_clas)
DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)
RandomForestClassifier¶
RandomForestClassifier V1¶
rf_1 = RandomForestClassifier(max_depth=2, random_state=42)
rf_1.fit(X_train_clas, y_train_clas)
RandomForestClassifier(max_depth=2, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=2, random_state=42)
RandomForestClassifier V2¶
rf_2 = RandomForestClassifier(max_depth=3, random_state=42)
rf_2.fit(X_train_clas, y_train_clas)
RandomForestClassifier(max_depth=3, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=3, random_state=42)
RandomForestClassifier V3¶
rf_3 = RandomForestClassifier(max_depth=15, random_state=42)
rf_3.fit(X_train_clas, y_train_clas)
RandomForestClassifier(max_depth=15, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=15, random_state=42)
RandomForestClassifier V4¶
rf_4 = RandomForestClassifier(max_depth=3, random_state=42,
min_samples_leaf=10, n_estimators=1000)
rf_4.fit(X_train_clas, y_train_clas)
RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)RandomForestClassifier V5¶
rf_5 = RandomForestClassifier(max_depth=3, random_state=42,
min_samples_leaf=10, n_estimators=1000, max_features='sqrt')
rf_5.fit(X_train_clas, y_train_clas)
RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)RandomForestClassifier V6¶
rf_6 = RandomForestClassifier(max_depth=3, random_state=42, min_samples_leaf=10,
n_estimators=1000, max_features='log2', max_samples=0.8)
rf_6.fit(X_train_clas, y_train_clas)
RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
min_samples_leaf=10, n_estimators=1000, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
min_samples_leaf=10, n_estimators=1000, random_state=42)GradientBoostingClassifier¶
GradientBoostingClassifier V1¶
gb_1 = GradientBoostingClassifier(max_depth=2, random_state=42)
gb_1.fit(X_train_clas, y_train_clas)
GradientBoostingClassifier(max_depth=2, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingClassifier(max_depth=2, random_state=42)
GradientBoostingClassifier V2¶
gb_2 = GradientBoostingClassifier(loss='exponential' ,learning_rate=0.1, n_estimators=150, max_depth=3, random_state=42)
gb_2.fit(X_train_clas, y_train_clas)
GradientBoostingClassifier(loss='exponential', n_estimators=150,
random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingClassifier(loss='exponential', n_estimators=150,
random_state=42)GradientBoostingClassifier V3¶
gb_3 = GradientBoostingClassifier(
learning_rate=0.001, n_estimators=1500, max_depth=3, random_state=42, min_samples_leaf=10)
gb_3.fit(X_train_clas, y_train_clas)
GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
n_estimators=1500, random_state=42)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
n_estimators=1500, random_state=42)KNeighborsClassifier¶
KNeighborsClassifier V1¶
knn_1 = KNeighborsClassifier(n_neighbors=2)
knn_1.fit(X_train_clas, y_train_clas)
KNeighborsClassifier(n_neighbors=2)In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
KNeighborsClassifier(n_neighbors=2)
Se genera una lista con los modelos
models = [ dt, rf, gb, knn,
dt_1, dt_2, dt_3, dt_4,
rf_1, rf_2, rf_3, rf_4, rf_5, rf_6,
gb_1, gb_2, gb_3,
knn_1]
Vista del Matriz de confusión y suma de aciertos¶
# matriz de confusion para cada modelo de clasificacion
from sklearn.metrics import confusion_matrix, classification_report
i=1
for model in models:
y_pred_clas = model.predict(X_test_clas)
cm = confusion_matrix(y_test_clas, y_pred_clas)
print(f'{i}° Modelo de Clasificación -> {model}\n')
# grafico de matriz de confusion con la diagonal en un color distinto
plt.figure(figsize=(3, 3))
sns.heatmap(cm, annot=True, fmt='g', cmap='Blues')
plt.xlabel('Predicted')
plt.ylabel('True')
plt.title('Matriz de Confusión del Modelo')
plt.show()
print(
f'Suma de la diagonal de la matriz de confusión del modelo es: {cm.trace()}\n')
print('-'*100,'\n')
i += 1
1° Modelo de Clasificación -> DecisionTreeClassifier()
Suma de la diagonal de la matriz de confusión del modelo es: 35090 ---------------------------------------------------------------------------------------------------- 2° Modelo de Clasificación -> RandomForestClassifier()
Suma de la diagonal de la matriz de confusión del modelo es: 38149 ---------------------------------------------------------------------------------------------------- 3° Modelo de Clasificación -> GradientBoostingClassifier()
Suma de la diagonal de la matriz de confusión del modelo es: 36070 ---------------------------------------------------------------------------------------------------- 4° Modelo de Clasificación -> KNeighborsClassifier()
Suma de la diagonal de la matriz de confusión del modelo es: 32181 ---------------------------------------------------------------------------------------------------- 5° Modelo de Clasificación -> DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 31588 ---------------------------------------------------------------------------------------------------- 6° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 31588 ---------------------------------------------------------------------------------------------------- 7° Modelo de Clasificación -> DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 31588 ---------------------------------------------------------------------------------------------------- 8° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 31588 ---------------------------------------------------------------------------------------------------- 9° Modelo de Clasificación -> RandomForestClassifier(max_depth=2, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 31847 ---------------------------------------------------------------------------------------------------- 10° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 32098 ---------------------------------------------------------------------------------------------------- 11° Modelo de Clasificación -> RandomForestClassifier(max_depth=15, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 36208
----------------------------------------------------------------------------------------------------
12° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 32193
----------------------------------------------------------------------------------------------------
13° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 32193
----------------------------------------------------------------------------------------------------
14° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
min_samples_leaf=10, n_estimators=1000, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 32196 ---------------------------------------------------------------------------------------------------- 15° Modelo de Clasificación -> GradientBoostingClassifier(max_depth=2, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 34764
----------------------------------------------------------------------------------------------------
16° Modelo de Clasificación -> GradientBoostingClassifier(loss='exponential', n_estimators=150,
random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 36785
----------------------------------------------------------------------------------------------------
17° Modelo de Clasificación -> GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
n_estimators=1500, random_state=42)
Suma de la diagonal de la matriz de confusión del modelo es: 33261 ---------------------------------------------------------------------------------------------------- 18° Modelo de Clasificación -> KNeighborsClassifier(n_neighbors=2)
Suma de la diagonal de la matriz de confusión del modelo es: 32702 ----------------------------------------------------------------------------------------------------
Analisis de accuracy, sensibilidad, precisión y F1¶
# for que recorra la lista de modelos y que imprima el accuracy, precision, recall, f1-score de cada modelo
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
i = 1
for model in models:
y_pred_clas = model.predict(X_test_clas)
print(f'{i}° Modelo de Clasificación -> {model}\n')
print('-'*100)
print(f'El accuracy del modelo es {accuracy_score(y_test_clas, y_pred_clas):.2f}')
print(f'El precision del modelo es {precision_score(y_test_clas, y_pred_clas):.2f}')
print(f'El recall del modelo es {recall_score(y_test_clas, y_pred_clas):.2f}')
print(f'El f1-score del modelo es {f1_score(y_test_clas, y_pred_clas):.2f}\n')
print('-'*100,'\n')
i += 1
1° Modelo de Clasificación -> DecisionTreeClassifier()
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.80
El precision del modelo es 0.79
El recall del modelo es 0.80
El f1-score del modelo es 0.80
----------------------------------------------------------------------------------------------------
2° Modelo de Clasificación -> RandomForestClassifier()
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.86
El precision del modelo es 0.90
El recall del modelo es 0.82
El f1-score del modelo es 0.86
----------------------------------------------------------------------------------------------------
3° Modelo de Clasificación -> GradientBoostingClassifier()
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.82
El precision del modelo es 0.85
El recall del modelo es 0.77
El f1-score del modelo es 0.81
----------------------------------------------------------------------------------------------------
4° Modelo de Clasificación -> KNeighborsClassifier()
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.71
El recall del modelo es 0.78
El f1-score del modelo es 0.74
----------------------------------------------------------------------------------------------------
5° Modelo de Clasificación -> DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.70
El recall del modelo es 0.77
El f1-score del modelo es 0.73
----------------------------------------------------------------------------------------------------
6° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.70
El recall del modelo es 0.77
El f1-score del modelo es 0.73
----------------------------------------------------------------------------------------------------
7° Modelo de Clasificación -> DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.70
El recall del modelo es 0.77
El f1-score del modelo es 0.73
----------------------------------------------------------------------------------------------------
8° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.70
El recall del modelo es 0.77
El f1-score del modelo es 0.73
----------------------------------------------------------------------------------------------------
9° Modelo de Clasificación -> RandomForestClassifier(max_depth=2, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.72
El precision del modelo es 0.74
El recall del modelo es 0.68
El f1-score del modelo es 0.71
----------------------------------------------------------------------------------------------------
10° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.74
El recall del modelo es 0.70
El f1-score del modelo es 0.72
----------------------------------------------------------------------------------------------------
11° Modelo de Clasificación -> RandomForestClassifier(max_depth=15, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.82
El precision del modelo es 0.86
El recall del modelo es 0.77
El f1-score del modelo es 0.81
----------------------------------------------------------------------------------------------------
12° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.74
El recall del modelo es 0.71
El f1-score del modelo es 0.72
----------------------------------------------------------------------------------------------------
13° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.74
El recall del modelo es 0.71
El f1-score del modelo es 0.72
----------------------------------------------------------------------------------------------------
14° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
min_samples_leaf=10, n_estimators=1000, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.73
El precision del modelo es 0.74
El recall del modelo es 0.71
El f1-score del modelo es 0.72
----------------------------------------------------------------------------------------------------
15° Modelo de Clasificación -> GradientBoostingClassifier(max_depth=2, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.79
El precision del modelo es 0.81
El recall del modelo es 0.75
El f1-score del modelo es 0.78
----------------------------------------------------------------------------------------------------
16° Modelo de Clasificación -> GradientBoostingClassifier(loss='exponential', n_estimators=150,
random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.83
El precision del modelo es 0.87
El recall del modelo es 0.78
El f1-score del modelo es 0.83
----------------------------------------------------------------------------------------------------
17° Modelo de Clasificación -> GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
n_estimators=1500, random_state=42)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.75
El precision del modelo es 0.81
El recall del modelo es 0.66
El f1-score del modelo es 0.73
----------------------------------------------------------------------------------------------------
18° Modelo de Clasificación -> KNeighborsClassifier(n_neighbors=2)
----------------------------------------------------------------------------------------------------
El accuracy del modelo es 0.74
El precision del modelo es 0.79
El recall del modelo es 0.66
El f1-score del modelo es 0.72
----------------------------------------------------------------------------------------------------
Gráficos de la curva curva ROC/AUC¶
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.metrics import roc_curve, auc
def plot_roc_chart(model, X_test, y_test):
# calculate the fpr and tpr for all thresholds of the classification
probs = model.predict_proba(X_test)
preds = probs[:, 1]
fpr, tpr, threshold = metrics.roc_curve(y_test, preds)
roc_auc = metrics.auc(fpr, tpr)
# method I: plt
plt.figure(figsize=(3, 3))
plt.title('Receiver Operating Characteristic')
plt.plot(fpr, tpr, 'b', label='AUC = %0.2f' % roc_auc)
plt.legend(loc='lower right')
plt.plot([0, 1], [0, 1], 'r--')
plt.xlim([0, 1])
plt.ylim([0, 1])
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
return probs
Gráfico y comparación¶
# trazar la curva ROC/AUC para cada modelo de clasificacion comparando con las clasificaciones
from sklearn.metrics import roc_curve, auc
i = 1
for model in models:
y_pred_clas = model.predict(X_test_clas)
fpr, tpr, thresholds = roc_curve(y_test_clas, y_pred_clas)
roc_auc = auc(fpr, tpr)
accuaracy = accuracy_score(y_test_clas, y_pred_clas)
dif = roc_auc - accuaracy
print(f'{i}° Modelo de Clasificación -> {model}\n')
print('-'*100)
print(
f'El área bajo la curva ROC del modelo es {roc_auc:.2f} vs {accuaracy:.2f} de accuracy')
print(f'generando una diferencia de {dif:.2f}\n')
plot_roc_chart(model, X_test_clas, y_test_clas)
print('-'*100,'\n')
i += 1
1° Modelo de Clasificación -> DecisionTreeClassifier() ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.80 vs 0.80 de accuracy generando una diferencia de -0.00
---------------------------------------------------------------------------------------------------- 2° Modelo de Clasificación -> RandomForestClassifier() ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.86 vs 0.86 de accuracy generando una diferencia de 0.00
---------------------------------------------------------------------------------------------------- 3° Modelo de Clasificación -> GradientBoostingClassifier() ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.82 vs 0.82 de accuracy generando una diferencia de 0.00
---------------------------------------------------------------------------------------------------- 4° Modelo de Clasificación -> KNeighborsClassifier() ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy generando una diferencia de -0.00
---------------------------------------------------------------------------------------------------- 5° Modelo de Clasificación -> DecisionTreeClassifier(criterion='entropy', max_depth=2, random_state=42) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy generando una diferencia de -0.00
---------------------------------------------------------------------------------------------------- 6° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, random_state=42) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy generando una diferencia de -0.00
---------------------------------------------------------------------------------------------------- 7° Modelo de Clasificación -> DecisionTreeClassifier(criterion='log_loss', max_depth=2, random_state=42) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy generando una diferencia de -0.00
---------------------------------------------------------------------------------------------------- 8° Modelo de Clasificación -> DecisionTreeClassifier(max_depth=2, min_samples_leaf=10, random_state=42) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy generando una diferencia de -0.00
---------------------------------------------------------------------------------------------------- 9° Modelo de Clasificación -> RandomForestClassifier(max_depth=2, random_state=42) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.72 vs 0.72 de accuracy generando una diferencia de 0.00
---------------------------------------------------------------------------------------------------- 10° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, random_state=42) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy generando una diferencia de 0.00
---------------------------------------------------------------------------------------------------- 11° Modelo de Clasificación -> RandomForestClassifier(max_depth=15, random_state=42) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.82 vs 0.82 de accuracy generando una diferencia de 0.00
----------------------------------------------------------------------------------------------------
12° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)
----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy
generando una diferencia de 0.00
----------------------------------------------------------------------------------------------------
13° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, min_samples_leaf=10, n_estimators=1000,
random_state=42)
----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy
generando una diferencia de 0.00
----------------------------------------------------------------------------------------------------
14° Modelo de Clasificación -> RandomForestClassifier(max_depth=3, max_features='log2', max_samples=0.8,
min_samples_leaf=10, n_estimators=1000, random_state=42)
----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.73 vs 0.73 de accuracy
generando una diferencia de 0.00
---------------------------------------------------------------------------------------------------- 15° Modelo de Clasificación -> GradientBoostingClassifier(max_depth=2, random_state=42) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.79 vs 0.79 de accuracy generando una diferencia de 0.00
----------------------------------------------------------------------------------------------------
16° Modelo de Clasificación -> GradientBoostingClassifier(loss='exponential', n_estimators=150,
random_state=42)
----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.83 vs 0.83 de accuracy
generando una diferencia de 0.00
----------------------------------------------------------------------------------------------------
17° Modelo de Clasificación -> GradientBoostingClassifier(learning_rate=0.001, min_samples_leaf=10,
n_estimators=1500, random_state=42)
----------------------------------------------------------------------------------------------------
El área bajo la curva ROC del modelo es 0.75 vs 0.75 de accuracy
generando una diferencia de 0.00
---------------------------------------------------------------------------------------------------- 18° Modelo de Clasificación -> KNeighborsClassifier(n_neighbors=2) ---------------------------------------------------------------------------------------------------- El área bajo la curva ROC del modelo es 0.74 vs 0.74 de accuracy generando una diferencia de 0.00
----------------------------------------------------------------------------------------------------
Características más importantes¶
## Identifica las características más importantes del dataset usando RandomForest
for score, name in zip(rf_1.feature_importances_, X_train_clas.columns):
print(f'La característica {name} tiene un score de {score:.2f}')
La característica RainToday_Yes tiene un score de 0.39 La característica Humidity3pm tiene un score de 0.06 La característica Humidity9am tiene un score de 0.02 La característica RISK_MM tiene un score de 0.16 La característica Cloud3pm tiene un score de 0.04 La característica Sunshine tiene un score de 0.05 La característica Cloud9am tiene un score de 0.06 La característica Temp3pm tiene un score de 0.00 La característica MaxTemp tiene un score de 0.00 La característica Rainfall tiene un score de 0.15 La característica Evaporation tiene un score de 0.01 La característica Pressure3pm tiene un score de 0.00 La característica Pressure9am tiene un score de 0.00 La característica Location_Sabana tiene un score de 0.00 La característica Location_arido_calido tiene un score de 0.03 La característica Location_mediterraneo tiene un score de 0.01 La característica Location_semiarido_calido tiene un score de 0.02 La característica Location_tropical_humedo tiene un score de 0.00 La característica Date tiene un score de 0.00
Decisión¶
El algoritmo utilizado,será el modelo N° 9 RandomForestClassifier sin hiperparámetros ya que es el que mejor predice los Verdaderos negativos con 5.545, dando asi un recall de 81%, y también es el que nos da el mayor accuracy con un 0.85%
RandomForestClassifier() Accuracy: 0.85 Precision: 0.89 Recall: 0.81 F1-Score: 0.85 Este modelo presenta el mejor rendimiento general con los valores más altos de precisión y F1-score
Modelos no supervisado¶
Casos de uso para aprendizaje no supervisado¶
Para esto usaremos las columnas 'RainToday_Yes','Rainfall','Sunshine','Humidity3pm','Cloud3pm','Cloud9am','RainTomorrow_Yes','Humidity9am','WindGustSpeed','Pressure9am','Pressure3pm','MinTemp','WindSpeed9am','Temp9am','Temp3pm'
- Clasificación para saber si llovera mañana:
- Cluster 1: No
- Cluster 2: Si
- Clasificación por Tipo de clima:
- Cluster 1: Clima Tropical.
- Cluster 2: Clima Desértico.
- Cluster 3: Clima Mediterráneo.
- Cluster 4: Clima Oceánico.
Clusterización¶
Ya que nuestro caso de uso elegido es el Clasificación por Tipo de Cliente, tenemos como hipótesis usar aproximadamente 4-6 clusters usaremos un rango de 2 a 11, para cumplir con los 10 k's distintos solicitados
from sklearn.cluster import MiniBatchKMeans
from sklearn.metrics import silhouette_score
# Rango de clusters a probar
k_range = np.arange(2, 6)
# crear un df_clustering usando el df con las columnas
df_clustering_complete = df[['RainToday_Yes','Humidity3pm','Cloud3pm','Sunshine','Temp3pm','Rainfall','Pressure3pm',"Location_Sabana","Location_arido_calido","Location_mediterraneo","Location_semiarido_calido","Location_tropical_humedo", 'Date']]
# Normalizar el df_clustering
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
df_clustering = scaler.fit_transform(df_clustering_complete)
# Reducir la dimensionalidad del df_clustering a 2 dimensiones usando PCA
from sklearn.decomposition import PCA
pca = PCA(n_components=2)
df_clustering = pca.fit_transform(df_clustering)
# realizar el clustering con MiniBatchKMeans
inertia = []
silhouette = []
for k in k_range:
mbk = MiniBatchKMeans(n_clusters=k, batch_size=1000, random_state=42, n_init=10)
mbk.fit(df_clustering)
inertia.append(mbk.inertia_)
silhouette.append(silhouette_score(df_clustering, mbk.labels_))
# graficar la clusterizacion con el valor de k y el valor de rand separando los clusters por colores y mostrando el centroide de cada cluster, separando las clusters por colores y con lineas
plt.figure(figsize=(10, 5))
plt.scatter(df_clustering[:, 0], df_clustering[:, 1], c=mbk.labels_, cmap='rainbow')
plt.scatter(mbk.cluster_centers_[:, 0], mbk.cluster_centers_[:, 1], marker='*', s=200, c='#050505')
plt.title(f'Clustering con {k} clusters')
plt.show()
# relizar el metodo del codo para encontrar el numero de clusters optimo
plt.figure(figsize=(10, 5))
plt.plot(k_range, inertia, 'bx-')
plt.xlabel('k')
plt.ylabel('Inertia')
plt.title('Método del Codo')
plt.show()
# Graficar la puntuación de la silueta para diferentes valores de k
plt.figure(figsize=(10, 5))
plt.plot(k_range, silhouette, marker='o', linestyle='-', color='b')
plt.title('Puntuación de la Silueta vs Número de Clusters')
plt.xlabel('Número de Clusters')
plt.ylabel('Puntuación de la Silueta')
plt.show()
Utilizando la gráfica para ver cual tiene menor inercia hemos decidido el numero k=3 como codo
Decisión de clasificación¶
Ya que el algoritmo dio 3 clusters cambiaremos la definición anterior a la siguiente:
- Clasificación por tipo de Clima: Un ejemplo de clusterización sería:
- Cluster 1: Clima Tropical.
- Cluster 2: Clima Desértico.
- Cluster 3: Clima Mediterráneo.
Elección de regresión¶
Para determinar los mejores tres modelos de regresión seleccionaremos aquellos con el menor MSE y RMSE, y el mayor R², lo que indica un mejor rendimiento en términos de precisión y ajuste del modelo. Estos son los mejores tres modelos basados en estas métricas:
Modelo 2: RandomForestRegressor()
MSE: 0.100
RMSE: 0.316
R²: 0.60
Modelo 12: RandomForestRegressor(max_depth=40, max_samples=0.8, min_samples_leaf=20, min_samples_split=20, n_estimators=12, random_state=42)
MSE: 0.114
RMSE: 0.337
R²: 0.55
Modelo 6: GradientBoostingRegressor(n_estimators=500, random_state=42, tol=2)
MSE: 0.112
RMSE: 0.335
R²: 0.55
Según estos resultados el elegido será el Modelo 2: RandomForestRegressor(), lo cual no esperabamos al ser el modelo sin hiper parametros pero la vida nos da sorpresas todos los días.
Elección de clasificación¶
Por otra parte, aquí están los mejores tres modelos basados en el f1-score y teniendo en cuenta métricas como el accuracy, precision, recall y f1-score.:
Modelo 2: RandomForestClassifier()
Accuracy: 0.86
Precision: 0.90
Recall: 0.82
F1-Score: 0.86
Modelo 16: GradientBoostingClassifier(loss='exponential', n_estimators=150, random_state=42)
Accuracy: 0.83
Precision: 0.87
Recall: 0.78
F1-Score: 0.83
Modelo 3: GradientBoostingClassifier()
Accuracy: 0.82
Precision: 0.85
Recall: 0.77
F1-Score: 0.81
Estos modelos tienen los f1-scores más altos y, por lo tanto, son los mejores en términos de equilibrio entre precision y recall. Además, estos modelos también tienen altos valores de accuracy y precision, lo que sugiere un buen rendimiento general dando como elegido el Modelo 2: RandomForestClassifier(), siendo uno de los modelos probados sin hiper parámetros y logrando las mejores métricas.